db-d2/primevul-codebert-embeddings huggingface dataset:
Commit message: mwifiex: Fix possible buffer overflows in mwifiex_ret_wmm_get_status()

mwifiex_ret_wmm_get_status() calls memcpy() without checking the
destination size.Since the source is given from remote AP which
contains illegal wmm elements , this may trigger a heap buffer
overflow.
Fix it by putting the length check before calling memcpy().

Signed-off-by: Qing Xu <m1s5p6688@gmail.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
CVE: CVE-2020-12654
CWE: CWE-787
Vulnerability description: An issue was found in Linux kernel before 5.5.4. mwifiex_ret_wmm_get_status() in drivers/net/wireless/marvell/mwifiex/wmm.c allows a remote AP to trigger a heap-based buffer overflow because of an incorrect memcpy, aka CID-3a9b153c5591.

Project: linux

int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv,
			       const struct host_cmd_ds_command *resp)
{
	u8 *curr = (u8 *) &resp->params.get_wmm_status;
	uint16_t resp_len = le16_to_cpu(resp->size), tlv_len;
	int mask = IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK;
	bool valid = true;

	struct mwifiex_ie_types_data *tlv_hdr;
	struct mwifiex_ie_types_wmm_queue_status *tlv_wmm_qstatus;
	struct ieee_types_wmm_parameter *wmm_param_ie = NULL;
	struct mwifiex_wmm_ac_status *ac_status;

	mwifiex_dbg(priv->adapter, INFO,
		    "info: WMM: WMM_GET_STATUS cmdresp received: %d\n",
		    resp_len);

	while ((resp_len >= sizeof(tlv_hdr->header)) && valid) {
		tlv_hdr = (struct mwifiex_ie_types_data *) curr;
		tlv_len = le16_to_cpu(tlv_hdr->header.len);

		if (resp_len < tlv_len + sizeof(tlv_hdr->header))
			break;

		switch (le16_to_cpu(tlv_hdr->header.type)) {
		case TLV_TYPE_WMMQSTATUS:
			tlv_wmm_qstatus =
				(struct mwifiex_ie_types_wmm_queue_status *)
				tlv_hdr;
			mwifiex_dbg(priv->adapter, CMD,
				    "info: CMD_RESP: WMM_GET_STATUS:\t"
				    "QSTATUS TLV: %d, %d, %d\n",
				    tlv_wmm_qstatus->queue_index,
				    tlv_wmm_qstatus->flow_required,
				    tlv_wmm_qstatus->disabled);

			ac_status = &priv->wmm.ac_status[tlv_wmm_qstatus->
							 queue_index];
			ac_status->disabled = tlv_wmm_qstatus->disabled;
			ac_status->flow_required =
						tlv_wmm_qstatus->flow_required;
			ac_status->flow_created = tlv_wmm_qstatus->flow_created;
			break;

		case WLAN_EID_VENDOR_SPECIFIC:
			/*
			 * Point the regular IEEE IE 2 bytes into the Marvell IE
			 *   and setup the IEEE IE type and length byte fields
			 */

			wmm_param_ie =
				(struct ieee_types_wmm_parameter *) (curr +
								    2);
			wmm_param_ie->vend_hdr.len = (u8) tlv_len;
			wmm_param_ie->vend_hdr.element_id =
						WLAN_EID_VENDOR_SPECIFIC;

			mwifiex_dbg(priv->adapter, CMD,
				    "info: CMD_RESP: WMM_GET_STATUS:\t"
				    "WMM Parameter Set Count: %d\n",
				    wmm_param_ie->qos_info_bitmap & mask);

			memcpy((u8 *) &priv->curr_bss_params.bss_descriptor.
			       wmm_ie, wmm_param_ie,
			       wmm_param_ie->vend_hdr.len + 2);

			break;

		default:
			valid = false;
			break;
		}

		curr += (tlv_len + sizeof(tlv_hdr->header));
		resp_len -= (tlv_len + sizeof(tlv_hdr->header));
	}

	mwifiex_wmm_setup_queue_priorities(priv, wmm_param_ie);
	mwifiex_wmm_setup_ac_downgrade(priv);

	return 0;
}
Commit message: cookie-jar: bail if hostname is an empty string

There are several other ways to fix the problem with this function, but
skipping over all of the code is probably the simplest.

Fixes #3
CVE: CVE-2018-12910
CWE: CWE-125
Vulnerability description: The get_cookies function in soup-cookie-jar.c in libsoup 2.63.2 allows attackers to have unspecified impact via an empty hostname.

Project: libsoup

get_cookies (SoupCookieJar *jar, SoupURI *uri, gboolean for_http, gboolean copy_cookies)
{
	SoupCookieJarPrivate *priv;
	GSList *cookies, *domain_cookies;
	char *domain, *cur, *next_domain;
	GSList *new_head, *cookies_to_remove = NULL, *p;

	priv = soup_cookie_jar_get_instance_private (jar);

	if (!uri->host)
		return NULL;

	/* The logic here is a little weird, but the plan is that if
	 * uri->host is "www.foo.com", we will end up looking up
	 * cookies for ".www.foo.com", "www.foo.com", ".foo.com", and
	 * ".com", in that order. (Logic stolen from Mozilla.)
	 */
	cookies = NULL;
	domain = cur = g_strdup_printf (".%s", uri->host);
	next_domain = domain + 1;
	do {
		new_head = domain_cookies = g_hash_table_lookup (priv->domains, cur);
		while (domain_cookies) {
			GSList *next = domain_cookies->next;
			SoupCookie *cookie = domain_cookies->data;

			if (cookie->expires && soup_date_is_past (cookie->expires)) {
				cookies_to_remove = g_slist_append (cookies_to_remove,
								    cookie);
				new_head = g_slist_delete_link (new_head, domain_cookies);
				g_hash_table_insert (priv->domains,
						     g_strdup (cur),
						     new_head);
			} else if (soup_cookie_applies_to_uri (cookie, uri) &&
				   (for_http || !cookie->http_only))
				cookies = g_slist_append (cookies, copy_cookies ? soup_cookie_copy (cookie) : cookie);

			domain_cookies = next;
		}
		cur = next_domain;
		if (cur)
			next_domain = strchr (cur + 1, '.');
	} while (cur);
	g_free (domain);

	for (p = cookies_to_remove; p; p = p->next) {
		SoupCookie *cookie = p->data;

		soup_cookie_jar_changed (jar, cookie, NULL);
		soup_cookie_free (cookie);
	}
	g_slist_free (cookies_to_remove);

	return g_slist_sort_with_data (cookies, compare_cookies, jar);
}
Commit message: [ot-font] Fix hmtx wrong table length check

Discovered by libFuzzer.  Ouch!

https://github.com/behdad/harfbuzz/issues/139#issuecomment-148289957
CVE: CVE-2016-2052
CWE: CWE-703
Vulnerability description: Multiple unspecified vulnerabilities in HarfBuzz before 1.0.6, as used in Google Chrome before 48.0.2564.82, allow attackers to cause a denial of service or possibly have other impact via crafted data, as demonstrated by a buffer over-read resulting from an inverted length check in hb-ot-font.cc, a different issue than CVE-2015-8947.

Project: harfbuzz
File: hb-ot-font.cc

  inline void init (hb_face_t *face,
		    hb_tag_t _hea_tag, hb_tag_t _mtx_tag,
		    unsigned int default_advance_)
  {
    this->default_advance = default_advance_;
    this->num_metrics = face->get_num_glyphs ();

    hb_blob_t *_hea_blob = OT::Sanitizer<OT::_hea>::sanitize (face->reference_table (_hea_tag));
    const OT::_hea *_hea = OT::Sanitizer<OT::_hea>::lock_instance (_hea_blob);
    this->num_advances = _hea->numberOfLongMetrics;
    hb_blob_destroy (_hea_blob);

    this->blob = OT::Sanitizer<OT::_mtx>::sanitize (face->reference_table (_mtx_tag));
    if (unlikely (!this->num_advances ||
		  2 * (this->num_advances + this->num_metrics) < hb_blob_get_length (this->blob)))
    {
      this->num_metrics = this->num_advances = 0;
      hb_blob_destroy (this->blob);
      this->blob = hb_blob_get_empty ();
    }
    this->table = OT::Sanitizer<OT::_mtx>::lock_instance (this->blob);
  }
Commit message: drm/i915: Introduce a mutex for file_priv->context_idr

Define a mutex for the exclusive use of interacting with the per-file
context-idr, that was previously guarded by struct_mutex. This allows us
to reduce the coverage of struct_mutex, with a view to removing the last
bits coordinating GEM context later. (In the short term, we avoid taking
struct_mutex while using the extended constructor functions, preventing
some nasty recursion.)

v2: s/context_lock/context_idr_lock/

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190321140711.11190-2-chris@chris-wilson.co.uk
CVE: CVE-2020-7053
CWE: CWE-416
Vulnerability description: In the Linux kernel 4.14 longterm through 4.14.165 and 4.19 longterm through 4.19.96 (and 5.x before 5.2), there is a use-after-free (write) in the i915_ppgtt_close function in drivers/gpu/drm/i915/i915_gem_gtt.c, aka CID-7dc40713618c. This is related to i915_gem_context_destroy_ioctl in drivers/gpu/drm/i915/i915_gem_context.c.

Project: linux
File: i915_gem_context.c

int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
				   struct drm_file *file)
{
	struct drm_i915_gem_context_destroy *args = data;
	struct drm_i915_file_private *file_priv = file->driver_priv;
	struct i915_gem_context *ctx;
	int ret;

	if (args->pad != 0)
		return -EINVAL;

	if (args->ctx_id == DEFAULT_CONTEXT_HANDLE)
		return -ENOENT;

	ctx = i915_gem_context_lookup(file_priv, args->ctx_id);
	if (!ctx)
		return -ENOENT;

	ret = mutex_lock_interruptible(&dev->struct_mutex);
	if (ret)
		goto out;

	idr_remove(&file_priv->context_idr, ctx->user_handle);
	context_close(ctx);

	mutex_unlock(&dev->struct_mutex);

out:
	i915_gem_context_put(ctx);
	return 0;
}
Commit message: Limit lenght to INT_MAX bytes in rfbProcessFileTransferReadBuffer()

This ammends 15bb719c03cc70f14c36a843dcb16ed69b405707 fix for a heap
out-of-bound write access in rfbProcessFileTransferReadBuffer() when
reading a transfered file content in a server. The former fix did not
work on platforms with a 32-bit int type (expected by rfbReadExact()).

CVE-2018-15127
<https://github.com/LibVNC/libvncserver/issues/243>
<https://github.com/LibVNC/libvncserver/issues/273>
CVE: CVE-2018-20750
CWE: CWE-200
Vulnerability description: LibVNC through 0.9.12 contains a heap out-of-bounds write vulnerability in libvncserver/rfbserver.c. The fix for CVE-2018-15127 was incomplete.

Project: libvncserver
File: rfbserver.c

char *rfbProcessFileTransferReadBuffer(rfbClientPtr cl, uint32_t length)
{
    char *buffer=NULL;
    int   n=0;

    FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, NULL);

    /*
       We later alloc length+1, which might wrap around on 32-bit systems if length equals
       0XFFFFFFFF, i.e. SIZE_MAX for 32-bit systems. On 64-bit systems, a length of 0XFFFFFFFF
       will safely be allocated since this check will never trigger and malloc() can digest length+1
       without problems as length is a uint32_t.
    */
    if(length == SIZE_MAX) {
	rfbErr("rfbProcessFileTransferReadBuffer: too big file transfer length requested: %u", (unsigned int)length);
	rfbCloseClient(cl);
	return NULL;
    }

    if (length>0) {
        buffer=malloc((size_t)length+1);
        if (buffer!=NULL) {
            if ((n = rfbReadExact(cl, (char *)buffer, length)) <= 0) {
                if (n != 0)
                    rfbLogPerror("rfbProcessFileTransferReadBuffer: read");
                rfbCloseClient(cl);
                /* NOTE: don't forget to free(buffer) if you return early! */
                if (buffer!=NULL) free(buffer);
                return NULL;
            }
            /* Null Terminate */
            buffer[length]=0;
        }
    }
    return buffer;
}
Commit message: 790783 - buffer overread in XCF parser if version field...

...has no null terminator

Check for the presence of '\0' before using atoi() on the version
string. Patch slightly modified (mitch).
CVE: CVE-2017-17788
CWE: CWE-125
Vulnerability description: In GIMP 2.8.22, there is a stack-based buffer over-read in xcf_load_stream in app/xcf/xcf.c when there is no '\0' character after the version string.

Project: gimp

xcf_load_stream (Gimp          *gimp,
                 GInputStream  *input,
                 GFile         *input_file,
                 GimpProgress  *progress,
                 GError       **error)
{
  XcfInfo      info  = { 0, };
  const gchar *filename;
  GimpImage   *image = NULL;
  gchar        id[14];
  gboolean     success;

  g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
  g_return_val_if_fail (G_IS_INPUT_STREAM (input), NULL);
  g_return_val_if_fail (input_file == NULL || G_IS_FILE (input_file), NULL);
  g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL);
  g_return_val_if_fail (error == NULL || *error == NULL, NULL);

  if (input_file)
    filename = gimp_file_get_utf8_name (input_file);
  else
    filename = _("Memory Stream");

  info.gimp             = gimp;
  info.input            = input;
  info.seekable         = G_SEEKABLE (input);
  info.bytes_per_offset = 4;
  info.progress         = progress;
  info.file             = input_file;
  info.compression      = COMPRESS_NONE;

  if (progress)
    gimp_progress_start (progress, FALSE, _("Opening '%s'"), filename);

  success = TRUE;

  xcf_read_int8 (&info, (guint8 *) id, 14);

  if (! g_str_has_prefix (id, "gimp xcf "))
    {
      success = FALSE;
    }
  else if (strcmp (id + 9, "file") == 0)
    {
      info.file_version = 0;
    }
  else if (id[9] == 'v')
    {
      info.file_version = atoi (id + 10);
    }
  else
    {
      success = FALSE;
    }

  if (info.file_version >= 11)
    info.bytes_per_offset = 8;

  if (success)
    {
      if (info.file_version >= 0 &&
          info.file_version < G_N_ELEMENTS (xcf_loaders))
        {
          image = (*(xcf_loaders[info.file_version])) (gimp, &info, error);

          if (! image)
            success = FALSE;

          g_input_stream_close (info.input, NULL, NULL);
        }
      else
        {
          g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
                       _("XCF error: unsupported XCF file version %d "
                         "encountered"), info.file_version);
          success = FALSE;
        }
    }

  if (progress)
    gimp_progress_end (progress);

  return image;
}
Commit message: iio: imu: adis16400: fix memory leak

In adis_update_scan_mode_burst, if adis->buffer allocation fails release
the adis->xfer.

Signed-off-by: Navid Emamdoost <navid.emamdoost@gmail.com>
Reviewed-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
CVE: CVE-2019-19061
CWE: CWE-401
Vulnerability description: A memory leak in the adis_update_scan_mode_burst() function in drivers/iio/imu/adis_buffer.c in the Linux kernel before 5.3.9 allows attackers to cause a denial of service (memory consumption), aka CID-9c0530e898f3.

Project: linux
File: adis_buffer.c

static int adis_update_scan_mode_burst(struct iio_dev *indio_dev,
	const unsigned long *scan_mask)
{
	struct adis *adis = iio_device_get_drvdata(indio_dev);
	unsigned int burst_length;
	u8 *tx;

	/* All but the timestamp channel */
	burst_length = (indio_dev->num_channels - 1) * sizeof(u16);
	burst_length += adis->burst->extra_len;

	adis->xfer = kcalloc(2, sizeof(*adis->xfer), GFP_KERNEL);
	if (!adis->xfer)
		return -ENOMEM;

	adis->buffer = kzalloc(burst_length + sizeof(u16), GFP_KERNEL);
	if (!adis->buffer)
		return -ENOMEM;

	tx = adis->buffer + burst_length;
	tx[0] = ADIS_READ_REG(adis->burst->reg_cmd);
	tx[1] = 0;

	adis->xfer[0].tx_buf = tx;
	adis->xfer[0].bits_per_word = 8;
	adis->xfer[0].len = 2;
	adis->xfer[1].rx_buf = adis->buffer;
	adis->xfer[1].bits_per_word = 8;
	adis->xfer[1].len = burst_length;

	spi_message_init(&adis->msg);
	spi_message_add_tail(&adis->xfer[0], &adis->msg);
	spi_message_add_tail(&adis->xfer[1], &adis->msg);

	return 0;
}
Commit message: Fix bug #68027 - fix date parsing in XMLRPC lib
CVE: CVE-2014-3668
CWE: CWE-119
Vulnerability description: Buffer overflow in the date_from_ISO8601 function in the mkgmtime implementation in libxmlrpc/xmlrpc.c in the XMLRPC extension in PHP before 5.4.34, 5.5.x before 5.5.18, and 5.6.x before 5.6.2 allows remote attackers to cause a denial of service (application crash) via (1) a crafted first argument to the xmlrpc_set_type function or (2) a crafted argument to the xmlrpc_decode function, related to an out-of-bounds read operation.

Project: php-src
File: xmlrpc.c

static int date_from_ISO8601 (const char *text, time_t * value) {
   struct tm tm;
   int n;
   int i;
   char buf[30];
	

	if (strchr (text, '-')) {
		char *p = (char *) text, *p2 = buf;
		while (p && *p) {
			if (*p != '-') {
				*p2 = *p;
				p2++;
				if (p2-buf >= sizeof(buf)) {
					return -1;
				}
			}
			p++;
		}
			text = buf;
	}


   tm.tm_isdst = -1;

#define XMLRPC_IS_NUMBER(x) if (x < '0' || x > '9') return -1;

   n = 1000;
   tm.tm_year = 0;
   for(i = 0; i < 4; i++) {
      XMLRPC_IS_NUMBER(text[i])
      tm.tm_year += (text[i]-'0')*n;
      n /= 10;
   }
   n = 10;
   tm.tm_mon = 0;
   for(i = 0; i < 2; i++) {
      XMLRPC_IS_NUMBER(text[i])
      tm.tm_mon += (text[i+4]-'0')*n;
      n /= 10;
   }
   tm.tm_mon --;

   n = 10;
   tm.tm_mday = 0;
   for(i = 0; i < 2; i++) {
      XMLRPC_IS_NUMBER(text[i])
      tm.tm_mday += (text[i+6]-'0')*n;
      n /= 10;
   }

   n = 10;
   tm.tm_hour = 0;
   for(i = 0; i < 2; i++) {
      XMLRPC_IS_NUMBER(text[i])
      tm.tm_hour += (text[i+9]-'0')*n;
      n /= 10;
   }

   n = 10;
   tm.tm_min = 0;
   for(i = 0; i < 2; i++) {
      XMLRPC_IS_NUMBER(text[i])
      tm.tm_min += (text[i+12]-'0')*n;
      n /= 10;
   }

   n = 10;
   tm.tm_sec = 0;
   for(i = 0; i < 2; i++) {
      XMLRPC_IS_NUMBER(text[i])
      tm.tm_sec += (text[i+15]-'0')*n;
      n /= 10;
   }

   tm.tm_year -= 1900;

   *value = mkgmtime(&tm);

   return 0;

}
Commit message: of: unittest: fix memory leak in unittest_data_add

In unittest_data_add, a copy buffer is created via kmemdup. This buffer
is leaked if of_fdt_unflatten_tree fails. The release for the
unittest_data buffer is added.

Fixes: b951f9dc7f25 ("Enabling OF selftest to run without machine's devicetree")
Signed-off-by: Navid Emamdoost <navid.emamdoost@gmail.com>
Reviewed-by: Frank Rowand <frowand.list@gmail.com>
Signed-off-by: Rob Herring <robh@kernel.org>
CVE: CVE-2019-19049
CWE: CWE-401
Vulnerability description: A memory leak in the unittest_data_add() function in drivers/of/unittest.c in the Linux kernel before 5.3.10 allows attackers to cause a denial of service (memory consumption) by triggering of_fdt_unflatten_tree() failures, aka CID-e13de8fe0d6a. NOTE: third parties dispute the relevance of this because unittest.c can only be reached during boot

Project: linux
File: unittest.c

static int __init unittest_data_add(void)
{
	void *unittest_data;
	struct device_node *unittest_data_node, *np;
	/*
	 * __dtb_testcases_begin[] and __dtb_testcases_end[] are magically
	 * created by cmd_dt_S_dtb in scripts/Makefile.lib
	 */
	extern uint8_t __dtb_testcases_begin[];
	extern uint8_t __dtb_testcases_end[];
	const int size = __dtb_testcases_end - __dtb_testcases_begin;
	int rc;

	if (!size) {
		pr_warn("%s: No testcase data to attach; not running tests\n",
			__func__);
		return -ENODATA;
	}

	/* creating copy */
	unittest_data = kmemdup(__dtb_testcases_begin, size, GFP_KERNEL);
	if (!unittest_data)
		return -ENOMEM;

	of_fdt_unflatten_tree(unittest_data, NULL, &unittest_data_node);
	if (!unittest_data_node) {
		pr_warn("%s: No tree to attach; not running tests\n", __func__);
		return -ENODATA;
	}

	/*
	 * This lock normally encloses of_resolve_phandles()
	 */
	of_overlay_mutex_lock();

	rc = of_resolve_phandles(unittest_data_node);
	if (rc) {
		pr_err("%s: Failed to resolve phandles (rc=%i)\n", __func__, rc);
		of_overlay_mutex_unlock();
		return -EINVAL;
	}

	if (!of_root) {
		of_root = unittest_data_node;
		for_each_of_allnodes(np)
			__of_attach_node_sysfs(np);
		of_aliases = of_find_node_by_path("/aliases");
		of_chosen = of_find_node_by_path("/chosen");
		of_overlay_mutex_unlock();
		return 0;
	}

	/* attach the sub-tree to live tree */
	np = unittest_data_node->child;
	while (np) {
		struct device_node *next = np->sibling;

		np->parent = of_root;
		attach_node_and_children(np);
		np = next;
	}

	of_overlay_mutex_unlock();

	return 0;
}
Commit message: Don't store the output of ByteVector::toUInt() in int, use uint instead
CVE: CVE-2012-1108
CWE: CWE-20
Vulnerability description: The parse function in ogg/xiphcomment.cpp in TagLib 1.7 and earlier allows remote attackers to cause a denial of service (crash) via a crafted vendorLength field in an ogg file.

Project: taglib
File: xiphcomment.cpp

void Ogg::XiphComment::parse(const ByteVector &data)
{
  // The first thing in the comment data is the vendor ID length, followed by a
  // UTF8 string with the vendor ID.

  uint pos = 0;

  int vendorLength = data.mid(0, 4).toUInt(false);
  pos += 4;

  d->vendorID = String(data.mid(pos, vendorLength), String::UTF8);
  pos += vendorLength;

  // Next the number of fields in the comment vector.

  uint commentFields = data.mid(pos, 4).toUInt(false);
  pos += 4;

  if(commentFields > (data.size() - 8) / 4) {
    return;
  }

  for(uint i = 0; i < commentFields; i++) {

    // Each comment field is in the format "KEY=value" in a UTF8 string and has
    // 4 bytes before the text starts that gives the length.

    uint commentLength = data.mid(pos, 4).toUInt(false);
    pos += 4;

    String comment = String(data.mid(pos, commentLength), String::UTF8);
    pos += commentLength;
    if(pos > data.size()) {
      break;
    }

    int commentSeparatorPosition = comment.find("=");
    if(commentSeparatorPosition == -1) {
      break;
    }

    String key = comment.substr(0, commentSeparatorPosition);
    String value = comment.substr(commentSeparatorPosition + 1);

    addField(key, value, false);
  }
}
Commit message: - Fix Out of Bounds Write in sldns_bget_token_par(),
  reported by X41 D-Sec.
CVE: CVE-2019-25035
CWE: CWE-787
Vulnerability description: Unbound before 1.9.5 allows an out-of-bounds write in sldns_bget_token_par. NOTE: The vendor disputes that this is a vulnerability. Although the code may be vulnerable, a running Unbound installation cannot be remotely or locally exploited

Project: unbound
File: parse.c

sldns_bget_token_par(sldns_buffer *b, char *token, const char *delim,
	size_t limit, int* par, const char* skipw)
{
	int c, lc;
	int p; /* 0 -> no parentheses seen, >0 nr of ( seen */
	int com, quoted;
	char *t;
	size_t i;
	const char *d;
	const char *del;

	/* standard delimiters */
	if (!delim) {
		/* from isspace(3) */
		del = LDNS_PARSE_NORMAL;
	} else {
		del = delim;
	}

	p = (par?*par:0);
	i = 0;
	com = 0;
	quoted = 0;
	t = token;
	lc = 0;
	if (del[0] == '"') {
		quoted = 1;
	}

	while ((c = sldns_bgetc(b)) != EOF) {
		if (c == '\r') /* carriage return */
			c = ' ';
		if (c == '(' && lc != '\\' && !quoted) {
			/* this only counts for non-comments */
			if (com == 0) {
				if(par) (*par)++;
				p++;
			}
			lc = c;
			continue;
		}

		if (c == ')' && lc != '\\' && !quoted) {
			/* this only counts for non-comments */
			if (com == 0) {
				if(par) (*par)--;
				p--;
			}
			lc = c;
			continue;
		}

		if (p < 0) {
			/* more ) then ( */
			*t = '\0';
			return 0;
		}

		/* do something with comments ; */
		if (c == ';' && quoted == 0) {
			if (lc != '\\') {
				com = 1;
			}
		}
		if (c == '"' && com == 0 && lc != '\\') {
			quoted = 1 - quoted;
		}

		if (c == '\n' && com != 0) {
			/* comments */
			com = 0;
			*t = ' ';
			lc = c;
			continue;
		}

		if (com == 1) {
			*t = ' ';
			lc = c;
			continue;
		}

		if (c == '\n' && p != 0) {
			/* in parentheses */
			/* do not write ' ' if we want to skip spaces */
			if(!(skipw && (strchr(skipw, c)||strchr(skipw, ' '))))
				*t++ = ' ';
			lc = c;
			continue;
		}

		/* check to skip whitespace at start, but also after ( */
		if(skipw && i==0 && !com && !quoted && lc != '\\') {
			if(strchr(skipw, c)) {
				lc = c;
				continue;
			}
		}

		/* check if we hit the delim */
		for (d = del; *d; d++) {
			/* we can only exit if no parens or user tracks them */
                        if (c == *d && lc != '\\' && (p == 0 || par)) {
				goto tokenread;
                        }
		}

		i++;
		if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) {
			*t = '\0';
			return -1;
		}
		*t++ = c;

		if (c == '\\' && lc == '\\') {
			lc = 0;
		} else {
			lc = c;
		}
	}
	*t = '\0';
	if (i == 0) {
		/* nothing read */
		return -1;
	}
	if (!par && p != 0) {
		return -1;
	}
	return (ssize_t)i;

tokenread:
	if(*del == '"')
		/* do not skip over quotes after the string, they are part
		 * of the next string.  But skip over whitespace (if needed)*/
		sldns_bskipcs(b, del+1);
	else 	sldns_bskipcs(b, del);
	*t = '\0';

	if (!par && p != 0) {
		return -1;
	}
	return (ssize_t)i;
}