db-d2/primevul-codebert-embeddings huggingface dataset:
Commit message: CVE-2017-13032/RADIUS: Check whether a byte exists before testing its value.

Reverse the test in a for loop to test the length before testing whether
we have a null byte.

This fixes a buffer over-read discovered by Bhargava Shastry.

Add a test using the capture file supplied by the reporter(s), modified
so the capture file won't be rejected as an invalid capture.

Clean up other length tests while we're at it.
CVE: CVE-2017-13032
CWE: CWE-125
Vulnerability description: The RADIUS parser in tcpdump before 4.9.2 has a buffer over-read in print-radius.c:print_attr_string().

Project: tcpdump
File: print-radius.c

print_attr_string(netdissect_options *ndo,
                  register const u_char *data, u_int length, u_short attr_code)
{
   register u_int i;

   ND_TCHECK2(data[0],length);

   switch(attr_code)
    {
       case TUNNEL_PASS:
            if (length < 3)
              goto trunc;
            if (*data && (*data <=0x1F) )
               ND_PRINT((ndo, "Tag[%u] ", *data));
            else
              ND_PRINT((ndo, "Tag[Unused] "));
           data++;
           length--;
           ND_PRINT((ndo, "Salt %u ", EXTRACT_16BITS(data)));
           data+=2;
           length-=2;
        break;
      case TUNNEL_CLIENT_END:
      case TUNNEL_SERVER_END:
      case TUNNEL_PRIV_GROUP:
      case TUNNEL_ASSIGN_ID:
      case TUNNEL_CLIENT_AUTH:
      case TUNNEL_SERVER_AUTH:
            if (*data <= 0x1F)
            {
               if (length < 1)
                 goto trunc;
               if (*data)
                 ND_PRINT((ndo, "Tag[%u] ", *data));
               else
                ND_PRINT((ndo, "Tag[Unused] "));
              data++;
              length--;
            }
         break;
       case EGRESS_VLAN_NAME:
           if (length < 1)
              goto trunc;
            ND_PRINT((ndo, "%s (0x%02x) ",
                   tok2str(rfc4675_tagged,"Unknown tag",*data),
                   *data));
           data++;
           length--;
         break;
    }
 
   for (i=0; i < length && *data; i++, data++)
        ND_PRINT((ndo, "%c", (*data < 32 || *data > 126) ? '.' : *data));
 
    return;

   trunc:
      ND_PRINT((ndo, "%s", tstr));
}
Commit message: None
CVE: CVE-2017-12666
CWE: CWE-772
Vulnerability description: ImageMagick 7.0.6-2 has a memory leak vulnerability in WriteINLINEImage in coders/inline.c.

Project: ImageMagick

static MagickBooleanType WriteINLINEImage(const ImageInfo *image_info,
  Image *image)
{
  char
    *base64,
    message[MaxTextExtent];

  const MagickInfo
    *magick_info;

  ExceptionInfo
    *exception;

  Image
    *write_image;

  ImageInfo
    *write_info;

  MagickBooleanType
    status;

  size_t
    blob_length,
    encode_length;

  unsigned char
    *blob;

  /*
    Convert image to base64-encoding.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickSignature);
  assert(image != (Image *) NULL);
  assert(image->signature == MagickSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  exception=(&image->exception);
  write_info=CloneImageInfo(image_info);
  (void) SetImageInfo(write_info,1,exception);
  if (LocaleCompare(write_info->magick,"INLINE") == 0)
    (void) CopyMagickString(write_info->magick,image->magick,MaxTextExtent);
   magick_info=GetMagickInfo(write_info->magick,exception);
   if ((magick_info == (const MagickInfo *) NULL) ||
       (GetMagickMimeType(magick_info) == (const char *) NULL))
    {
      write_info=DestroyImageInfo(write_info);
      ThrowWriterException(CorruptImageError,"ImageTypeNotSupported");
    }
   (void) CopyMagickString(image->filename,write_info->filename,MaxTextExtent);
   blob_length=2048;
   write_image=CloneImage(image,0,0,MagickTrue,exception);
  if (write_image == (Image *) NULL)
    {
      write_info=DestroyImageInfo(write_info);
      return(MagickTrue);
    }
  blob=(unsigned char *) ImageToBlob(write_info,write_image,&blob_length,
    exception);
  write_image=DestroyImage(write_image);
  write_info=DestroyImageInfo(write_info);
  if (blob == (unsigned char *) NULL)
    return(MagickFalse);
  encode_length=0;
  base64=Base64Encode(blob,blob_length,&encode_length);
  blob=(unsigned char *) RelinquishMagickMemory(blob);
  if (base64 == (char *) NULL)
    ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
  /*
    Write base64-encoded image.
  */
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
  if (status == MagickFalse)
    {
      base64=DestroyString(base64);
      return(status);
    }
  (void) FormatLocaleString(message,MaxTextExtent,"data:%s;base64,",
    GetMagickMimeType(magick_info));
  (void) WriteBlobString(image,message);
  (void) WriteBlobString(image,base64);
  base64=DestroyString(base64);
  return(MagickTrue);
}
Commit message: arm64: KVM: pmu: Fix AArch32 cycle counter access

We're missing the handling code for the cycle counter accessed
from a 32bit guest, leading to unexpected results.

Cc: stable@vger.kernel.org # 4.6+
Signed-off-by: Wei Huang <wei@redhat.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
CVE: CVE-2017-12168
CWE: CWE-617
Vulnerability description: The access_pmu_evcntr function in arch/arm64/kvm/sys_regs.c in the Linux kernel before 4.8.11 allows privileged KVM guest OS users to cause a denial of service (assertion failure and host OS crash) by accessing the Performance Monitors Cycle Count Register (PMCCNTR).

Project: linux
File: sys_regs.c

static bool access_pmu_evcntr(struct kvm_vcpu *vcpu,
			      struct sys_reg_params *p,
			      const struct sys_reg_desc *r)
{
	u64 idx;

	if (!kvm_arm_pmu_v3_ready(vcpu))
		return trap_raz_wi(vcpu, p, r);

	if (r->CRn == 9 && r->CRm == 13) {
		if (r->Op2 == 2) {
			/* PMXEVCNTR_EL0 */
			if (pmu_access_event_counter_el0_disabled(vcpu))
				return false;

			idx = vcpu_sys_reg(vcpu, PMSELR_EL0)
			      & ARMV8_PMU_COUNTER_MASK;
		} else if (r->Op2 == 0) {
			/* PMCCNTR_EL0 */
			if (pmu_access_cycle_counter_el0_disabled(vcpu))
				return false;
 
 			idx = ARMV8_PMU_CYCLE_IDX;
 		} else {
			return false;
 		}
	} else if (r->CRn == 0 && r->CRm == 9) {
		/* PMCCNTR */
		if (pmu_access_event_counter_el0_disabled(vcpu))
			return false;

		idx = ARMV8_PMU_CYCLE_IDX;
 	} else if (r->CRn == 14 && (r->CRm & 12) == 8) {
 		/* PMEVCNTRn_EL0 */
 		if (pmu_access_event_counter_el0_disabled(vcpu))
 			return false;
 
 		idx = ((r->CRm & 3) << 3) | (r->Op2 & 7);
 	} else {
		return false;
 	}
 
 	if (!pmu_counter_idx_valid(vcpu, idx))
		return false;

	if (p->is_write) {
		if (pmu_access_el0_disabled(vcpu))
			return false;

		kvm_pmu_set_counter_value(vcpu, idx, p->regval);
	} else {
		p->regval = kvm_pmu_get_counter_value(vcpu, idx);
	}

	return true;
}
Commit message: [gsm] Delay the creation of the GsmXSMPClient until it really exists

We used to create the GsmXSMPClient before the XSMP connection is really
accepted. This can lead to some issues, though. An example is:
https://bugzilla.gnome.org/show_bug.cgi?id=598211#c19. Quoting:

 "What is happening is that a new client (probably metacity in your
 case) is opening an ICE connection in the GSM_MANAGER_PHASE_END_SESSION
 phase, which causes a new GsmXSMPClient to be added to the client
 store. The GSM_MANAGER_PHASE_EXIT phase then begins before the client
 has had a chance to establish a xsmp connection, which means that
 client->priv->conn will not be initialized at the point that xsmp_stop
 is called on the new unregistered client."

The fix is to create the GsmXSMPClient object when there's a real XSMP
connection. This implies moving the timeout that makes sure we don't
have an empty client to the XSMP server.

https://bugzilla.gnome.org/show_bug.cgi?id=598211
CVE: CVE-2017-11171
CWE: CWE-835
Vulnerability description: Bad reference counting in the context of accept_ice_connection() in gsm-xsmp-server.c in old versions of gnome-session up until version 2.29.92 allows a local attacker to establish ICE connections to gnome-session with invalid authentication data (an invalid magic cookie). Each failed authentication attempt will leak a file descriptor in gnome-session. When the maximum number of file descriptors is exhausted in the gnome-session process, it will enter an infinite loop trying to communicate without success, consuming 100% of the CPU. The graphical session associated with the gnome-session process will stop working correctly, because communication with gnome-session is no longer possible.

Project: gnome-session

_client_protocol_timeout (GsmXSMPClient *client)

Project: gnome-session
File: gsm-xsmp-client.c

gsm_xsmp_client_disconnect (GsmXSMPClient *client)
{
        if (client->priv->watch_id > 0) {
                g_source_remove (client->priv->watch_id);
        }

        if (client->priv->conn != NULL) {
                SmsCleanUp (client->priv->conn);
        }

        if (client->priv->ice_connection != NULL) {
                 IceSetShutdownNegotiation (client->priv->ice_connection, FALSE);
                 IceCloseConnection (client->priv->ice_connection);
         }
 }
Commit message: virtio-console: avoid DMA from stack

put_chars() stuffs the buffer it gets into an sg, but that buffer may be
on the stack. This breaks with CONFIG_VMAP_STACK=y (for me, it
manifested as printks getting turned into NUL bytes).

Signed-off-by: Omar Sandoval <osandov@fb.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Amit Shah <amit.shah@redhat.com>
CVE: CVE-2017-8067
CWE: CWE-119
Vulnerability description: drivers/char/virtio_console.c in the Linux kernel 4.9.x and 4.10.x before 4.10.12 interacts incorrectly with the CONFIG_VMAP_STACK option, which allows local users to cause a denial of service (system crash or memory corruption) or possibly have unspecified other impact by leveraging use of more than one virtual page for a DMA scatterlist.

Project: linux
File: virtio_console.c

static int put_chars(u32 vtermno, const char *buf, int count)
 {
 	struct port *port;
 	struct scatterlist sg[1];
	void *data;
	int ret;
 
 	if (unlikely(early_put_chars))
 		return early_put_chars(vtermno, buf, count);

	port = find_port_by_vtermno(vtermno);
 	if (!port)
 		return -EPIPE;
 
	data = kmemdup(buf, count, GFP_ATOMIC);
	if (!data)
		return -ENOMEM;

	sg_init_one(sg, data, count);
	ret = __send_to_port(port, sg, 1, count, data, false);
	kfree(data);
	return ret;
 }
Commit message: Fix crash in fuzzed wasm r2_hoobr_consume_init_expr
CVE: CVE-2017-7854
CWE: CWE-125
Vulnerability description: The consume_init_expr function in wasm.c in radare2 1.3.0 allows remote attackers to cause a denial of service (heap-based buffer over-read and application crash) via a crafted Web Assembly file.

Project: radare2
File: wasm.c

 static RList *r_bin_wasm_get_data_entries (RBinWasmObj *bin, RBinWasmSection *sec) {
 	RList *ret = NULL;
 	RBinWasmDataEntry *ptr = NULL;
	ut32 len =  sec->payload_len;
 
 	if (!(ret = r_list_newf ((RListFree)free))) {
 		return NULL;
 	}
 
 	ut8* buf = bin->buf->buf + (ut32)sec->payload_data;
	int buflen = bin->buf->length - (ut32)sec->payload_data;
 	ut32 count = sec->count;
 	ut32 i = 0, r = 0;
 	size_t n = 0;
 
	while (i < len && len < buflen && r < count) {
 		if (!(ptr = R_NEW0 (RBinWasmDataEntry))) {
 			return ret;
 		}
 		if (!(consume_u32 (buf + i, buf + len, &ptr->index, &i))) {
			goto beach;
		}
		if (i + 4 >= buflen) {
			goto beach;
 		}
 		if (!(n = consume_init_expr (buf + i, buf + len, R_BIN_WASM_END_OF_CODE, NULL, &i))) {
			goto beach;
 		}
 		ptr->offset.len = n;
 		if (!(consume_u32 (buf + i, buf + len, &ptr->size, &i))) {	
			goto beach;
		}
		if (i + 4 >= buflen) {
			goto beach;
 		}
 		ptr->data = sec->payload_data + i;
 
 		r_list_append (ret, ptr);
 
 		r += 1;
 
 	}
	return ret;
beach:
	free (ptr);
 	return ret;
 }
Commit message: Detect invalid port in xp_socket parse ip address

For historical reasons, fsockopen() accepts the port and hostname
separately: fsockopen('127.0.0.1', 80)

However, with the introdcution of stream transports in PHP 4.3,
it became possible to include the port in the hostname specifier:

fsockopen('127.0.0.1:80')
Or more formally: fsockopen('tcp://127.0.0.1:80')

Confusing results when these two forms are combined, however.
fsockopen('127.0.0.1:80', 443) results in fsockopen() attempting
to connect to '127.0.0.1:80:443' which any reasonable stack would
consider invalid.

Unfortunately, PHP parses the address looking for the first colon
(with special handling for IPv6, don't worry) and calls atoi()
from there.  atoi() in turn, simply stops parsing at the first
non-numeric character and returns the value so far.

The end result is that the explicitly supplied port is treated
as ignored garbage, rather than producing an error.

This diff replaces atoi() with strtol() and inspects the
stop character.  If additional "garbage" of any kind is found,
it fails and returns an error.
CVE: CVE-2017-7189
CWE: CWE-918
Vulnerability description: main/streams/xp_socket.c in PHP 7.x before 2017-03-07 misparses fsockopen calls, such as by interpreting fsockopen('127.0.0.1:80', 443) as if the address/port were 127.0.0.1:80:443, which is later truncated to 127.0.0.1:80. This behavior has a security risk if the explicitly provided port number (i.e., 443 in this example) is hardcoded into an application as a security policy, but the hostname argument (i.e., 127.0.0.1:80 in this example) is obtained from untrusted input.

Project: php-src
File: xp_socket.c

static inline char *parse_ip_address_ex(const char *str, size_t str_len, int *portno, int get_err, zend_string **err)
{
	char *colon;
 	char *host = NULL;
 
 #ifdef HAVE_IPV6
 	if (*(str) == '[' && str_len > 1) {
 		/* IPV6 notation to specify raw address with port (i.e. [fe80::1]:80) */
		char *p = memchr(str + 1, ']', str_len - 2), *e = NULL;
 		if (!p || *(p + 1) != ':') {
 			if (get_err) {
 				*err = strpprintf(0, "Failed to parse IPv6 address \"%s\"", str);
 			}
 			return NULL;
 		}
		*portno = strtol(p + 2, &e, 10);
		if (e && *e) {
			if (get_err) {
				*err = strpprintf(0, "Failed to parse address \"%s\"", str);
			}
			return NULL;
		}
 		return estrndup(str + 1, p - str - 1);
 	}
 #endif

 	if (str_len) {
 		colon = memchr(str, ':', str_len - 1);
 	} else {
 		colon = NULL;
 	}

 	if (colon) {
		char *e = NULL;
		*portno = strtol(colon + 1, &e, 10);
		if (!e || !*e) {
			return estrndup(str, colon - str);
 		}
 	}
 
	if (get_err) {
		*err = strpprintf(0, "Failed to parse address \"%s\"", str);
	}
	return NULL;
 }
Commit message: src/aiff.c: Fix a buffer read overflow

Secunia Advisory SA76717.

Found by: Laurent Delosieres, Secunia Research at Flexera Software
CVE: CVE-2017-6892
CWE: CWE-119
Vulnerability description: In libsndfile version 1.0.28, an error in the "aiff_read_chanmap()" function (aiff.c) can be exploited to cause an out-of-bounds read memory access via a specially crafted AIFF file.

Project: libsndfile
File: aiff.c

aiff_read_chanmap (SF_PRIVATE * psf, unsigned dword)
{	const AIFF_CAF_CHANNEL_MAP * map_info ;
	unsigned channel_bitmap, channel_decriptions, bytesread ;
	int layout_tag ;

	bytesread = psf_binheader_readf (psf, "444", &layout_tag, &channel_bitmap, &channel_decriptions) ;

	if ((map_info = aiff_caf_of_channel_layout_tag (layout_tag)) == NULL)
		return 0 ;

	psf_log_printf (psf, "  Tag    : %x\n", layout_tag) ;
	if (map_info)
		psf_log_printf (psf, "  Layout : %s\n", map_info->name) ;

	if (bytesread < dword)
 		psf_binheader_readf (psf, "j", dword - bytesread) ;
 
 	if (map_info->channel_map != NULL)
	{	size_t chanmap_size = SF_MIN (psf->sf.channels, layout_tag & 0xffff) * sizeof (psf->channel_map [0]) ;
 
 		free (psf->channel_map) ;
 
		if ((psf->channel_map = malloc (chanmap_size)) == NULL)
			return SFE_MALLOC_FAILED ;

		memcpy (psf->channel_map, map_info->channel_map, chanmap_size) ;
		} ;

	return 0 ;
} /* aiff_read_chanmap */
Commit message: Exit gracefully in case of corrupted filters (Closes issue #782)
CVE: CVE-2017-6430
CWE: CWE-125
Vulnerability description: The compile_tree function in ef_compiler.c in the Etterfilter utility in Ettercap 0.8.2 and earlier allows remote attackers to cause a denial of service (out-of-bounds read) via a crafted filter.

Project: ettercap
File: ef_main.c

 int main(int argc, char *argv[])
 {
   int ret_value = 0;
    libettercap_init();
    ef_globals_alloc();
    select_text_interface();
   libettercap_ui_init();
   /* etterfilter copyright */
   fprintf(stdout, "\n" EC_COLOR_BOLD "%s %s" EC_COLOR_END " copyright %s %s\n\n", 
                      PROGRAM, EC_VERSION, EC_COPYRIGHT, EC_AUTHORS);
 
   /* initialize the line number */
   EF_GBL->lineno = 1;
  
   /* getopt related parsing...  */
   parse_options(argc, argv);

   /* set the input for source file */
   if (EF_GBL_OPTIONS->source_file) {
      yyin = fopen(EF_GBL_OPTIONS->source_file, "r");
      if (yyin == NULL)
         FATAL_ERROR("Input file not found !");
   } else {
      FATAL_ERROR("No source file.");
   }

   /* no buffering */
   setbuf(yyin, NULL);
   setbuf(stdout, NULL);
   setbuf(stderr, NULL);

   
   /* load the tables in etterfilter.tbl */
   load_tables();
   /* load the constants in etterfilter.cnt */
   load_constants();

   /* print the message */
   fprintf(stdout, "\n Parsing source file \'%s\' ", EF_GBL_OPTIONS->source_file);
   fflush(stdout);

   ef_debug(1, "\n");

   /* begin the parsing */
   if (yyparse() == 0)
      fprintf(stdout, " done.\n\n");
   else
       fprintf(stdout, "\n\nThe script contains errors...\n\n");
   
    /* write to file */
   ret_value = write_output();
   if (ret_value == -E_NOTHANDLED)
      FATAL_ERROR("Cannot write output file (%s): the filter is not correctly handled.", EF_GBL_OPTIONS->output_file);
   else if (ret_value == -E_INVALID)
      FATAL_ERROR("Cannot write output file (%s): the filter format is not correct. ", EF_GBL_OPTIONS->output_file);

    ef_globals_free();
    return 0;
 }
Commit message: Fail with negative lha->compsize in lha_read_file_header_1()
Fixes a heap buffer overflow reported in Secunia SA74169
CVE: CVE-2017-5601
CWE: CWE-125
Vulnerability description: An error in the lha_read_file_header_1() function (archive_read_support_format_lha.c) in libarchive 3.2.2 allows remote attackers to trigger an out-of-bounds read memory access and subsequently cause a crash via a specially crafted archive.

Project: libarchive
File: archive_read_support_format_lha.c

lha_read_file_header_1(struct archive_read *a, struct lha *lha)
{
	const unsigned char *p;
	size_t extdsize;
	int i, err, err2;
	int namelen, padding;
	unsigned char headersum, sum_calculated;

	err = ARCHIVE_OK;

	if ((p = __archive_read_ahead(a, H1_FIXED_SIZE, NULL)) == NULL)
		return (truncated_error(a));

	lha->header_size = p[H1_HEADER_SIZE_OFFSET] + 2;
	headersum = p[H1_HEADER_SUM_OFFSET];
	/* Note: An extended header size is included in a compsize. */
	lha->compsize = archive_le32dec(p + H1_COMP_SIZE_OFFSET);
	lha->origsize = archive_le32dec(p + H1_ORIG_SIZE_OFFSET);
	lha->mtime = lha_dos_time(p + H1_DOS_TIME_OFFSET);
	namelen = p[H1_NAME_LEN_OFFSET];
	/* Calculate a padding size. The result will be normally 0 only(?) */
	padding = ((int)lha->header_size) - H1_FIXED_SIZE - namelen;

	if (namelen > 230 || padding < 0)
		goto invalid;

	if ((p = __archive_read_ahead(a, lha->header_size, NULL)) == NULL)
		return (truncated_error(a));

	for (i = 0; i < namelen; i++) {
		if (p[i + H1_FILE_NAME_OFFSET] == 0xff)
			goto invalid;/* Invalid filename. */
	}
	archive_strncpy(&lha->filename, p + H1_FILE_NAME_OFFSET, namelen);
	lha->crc = archive_le16dec(p + H1_FILE_NAME_OFFSET + namelen);
	lha->setflag |= CRC_IS_SET;

	sum_calculated = lha_calcsum(0, p, 2, lha->header_size - 2);
	/* Consume used bytes but not include `next header size' data
	 * since it will be consumed in lha_read_file_extended_header(). */
	__archive_read_consume(a, lha->header_size - 2);

	/* Read extended headers */
	err2 = lha_read_file_extended_header(a, lha, NULL, 2,
	    (size_t)(lha->compsize + 2), &extdsize);
	if (err2 < ARCHIVE_WARN)
		return (err2);
	if (err2 < err)
		err = err2;
 	/* Get a real compressed file size. */
 	lha->compsize -= extdsize - 2;
 
	if (lha->compsize < 0)
		goto invalid;	/* Invalid compressed file size */

 	if (sum_calculated != headersum) {
 		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
 		    "LHa header sum error");
		return (ARCHIVE_FATAL);
	}
	return (err);
invalid:
	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
	    "Invalid LHa header");
	return (ARCHIVE_FATAL);
}
Commit message: KEYS: Remove key_type::match in favour of overriding default by match_preparse

A previous patch added a ->match_preparse() method to the key type.  This is
allowed to override the function called by the iteration algorithm.
Therefore, we can just set a default that simply checks for an exact match of
the key description with the original criterion data and allow match_preparse
to override it as needed.

The key_type::match op is then redundant and can be removed, as can the
user_match() function.

Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
CVE: CVE-2017-2647
CWE: CWE-476
Vulnerability description: The KEYS subsystem in the Linux kernel before 3.18 allows local users to gain privileges or cause a denial of service (NULL pointer dereference and system crash) via vectors involving a NULL value for a certain match field, related to the keyring_search_iterator function in keyring.c.

Project: linux

int user_match(const struct key *key, const struct key_match_data *match_data)
Commit message: Fix #72696: imagefilltoborder stackoverflow on truecolor images

We must not allow negative color values be passed to
gdImageFillToBorder(), because that can lead to infinite recursion
since the recursion termination condition will not necessarily be met.
CVE: CVE-2016-9933
CWE: CWE-119
Vulnerability description: Stack consumption vulnerability in the gdImageFillToBorder function in gd.c in the GD Graphics Library (aka libgd) before 2.2.2, as used in PHP before 5.6.28 and 7.x before 7.0.13, allows remote attackers to cause a denial of service (segmentation violation) via a crafted imagefilltoborder call that triggers use of a negative color value.

Project: php-src

void gdImageFillToBorder (gdImagePtr im, int x, int y, int border, int color)
{
	int lastBorder;
	/* Seek left */
 	int leftLimit = -1, rightLimit;
 	int i, restoreAlphaBlending = 0;
 
	if (border < 0 || color < 0) {
 		/* Refuse to fill to a non-solid border */
 		return;
 	}

	if (!im->trueColor) {
		if ((color > (im->colorsTotal - 1)) || (border > (im->colorsTotal - 1)) || (color < 0)) {
			return;
		}
	}

	restoreAlphaBlending = im->alphaBlendingFlag;
	im->alphaBlendingFlag = 0;

	if (x >= im->sx) {
		x = im->sx - 1;
	} else if (x < 0) {
		x = 0;
	}
	if (y >= im->sy) {
		y = im->sy - 1;
	} else if (y < 0) {
		y = 0;
	}

	for (i = x; i >= 0; i--) {
		if (gdImageGetPixel(im, i, y) == border) {
			break;
		}
		gdImageSetPixel(im, i, y, color);
		leftLimit = i;
	}
	if (leftLimit == -1) {
		im->alphaBlendingFlag = restoreAlphaBlending;
		return;
	}
	/* Seek right */
	rightLimit = x;
	for (i = (x + 1); i < im->sx; i++) {
		if (gdImageGetPixel(im, i, y) == border) {
			break;
		}
		gdImageSetPixel(im, i, y, color);
		rightLimit = i;
	}
	/* Look at lines above and below and start paints */
	/* Above */
	if (y > 0) {
		lastBorder = 1;
		for (i = leftLimit; i <= rightLimit; i++) {
			int c = gdImageGetPixel(im, i, y - 1);
			if (lastBorder) {
				if ((c != border) && (c != color)) {
					gdImageFillToBorder(im, i, y - 1, border, color);
					lastBorder = 0;
				}
			} else if ((c == border) || (c == color)) {
				lastBorder = 1;
			}
		}
	}

	/* Below */
	if (y < ((im->sy) - 1)) {
		lastBorder = 1;
		for (i = leftLimit; i <= rightLimit; i++) {
			int c = gdImageGetPixel(im, i, y + 1);

			if (lastBorder) {
				if ((c != border) && (c != color)) {
					gdImageFillToBorder(im, i, y + 1, border, color);
					lastBorder = 0;
				}
			} else if ((c == border) || (c == color)) {
				lastBorder = 1;
			}
		}
	}
	im->alphaBlendingFlag = restoreAlphaBlending;
}