diff options
author | Stanislav Malyshev <stas@php.net> | 2019-01-06 11:57:16 -0800 |
---|---|---|
committer | Stanislav Malyshev <stas@php.net> | 2019-01-06 11:57:16 -0800 |
commit | fe820fcba616a736b80e911cfc132388acd35ace (patch) | |
tree | d958a1c3d69c8089081a807f4fb8cdfa80007422 | |
parent | 41af1e6781386cf540926ba9d1ff59a3402f8e01 (diff) | |
parent | 8d3dfabef459fe7815e8ea2fd68753fd17859d7b (diff) | |
download | php-git-fe820fcba616a736b80e911cfc132388acd35ace.tar.gz |
Merge branch 'PHP-7.1' into PHP-7.2
* PHP-7.1:
Fix #77369 - memcpy with negative length via crafted DNS response
Fix more issues with encodilng length
Fix #77270: imagecolormatch Out Of Bounds Write on Heap
Fix bug #77380 (Global out of bounds read in xmlrpc base64 code)
Fix bug #77371 (heap buffer overflow in mb regex functions - compile_string_node)
Fix bug #77370 - check that we do not read past buffer end when parsing multibytes
Fix #77269: Potential unsigned underflow in gdImageScale
Fix bug #77247 (heap buffer overflow in phar_detect_phar_fname_ext)
Fix bug #77242 (heap out of bounds read in xmlrpc_decode())
Regenerate certs for openssl tests
-rw-r--r-- | ext/gd/libgd/gd_color_match.c | 4 | ||||
-rw-r--r-- | ext/gd/libgd/gd_interpolation.c | 18 | ||||
-rw-r--r-- | ext/gd/tests/bug77269.phpt | 21 | ||||
-rw-r--r-- | ext/gd/tests/bug77270.phpt | 18 | ||||
-rw-r--r-- | ext/mbstring/oniguruma/src/regcomp.c | 10 | ||||
-rw-r--r-- | ext/mbstring/oniguruma/src/regparse.c | 6 | ||||
-rw-r--r-- | ext/mbstring/oniguruma/src/regparse.h | 12 | ||||
-rw-r--r-- | ext/mbstring/tests/bug77370.phpt | 13 | ||||
-rw-r--r-- | ext/mbstring/tests/bug77371.phpt | 10 | ||||
-rw-r--r-- | ext/mbstring/tests/bug77381.phpt | 16 | ||||
-rw-r--r-- | ext/phar/phar.c | 2 | ||||
-rw-r--r-- | ext/phar/tests/bug77247.phpt | 14 | ||||
-rw-r--r-- | ext/standard/dns.c | 7 | ||||
-rw-r--r-- | ext/xmlrpc/libxmlrpc/base64.c | 4 | ||||
-rw-r--r-- | ext/xmlrpc/libxmlrpc/xml_element.c | 3 | ||||
-rw-r--r-- | ext/xmlrpc/tests/bug77242.phpt | 10 | ||||
-rw-r--r-- | ext/xmlrpc/tests/bug77380.phpt | 17 |
17 files changed, 166 insertions, 19 deletions
diff --git a/ext/gd/libgd/gd_color_match.c b/ext/gd/libgd/gd_color_match.c index a4e56b1c40..e6f539bc75 100644 --- a/ext/gd/libgd/gd_color_match.c +++ b/ext/gd/libgd/gd_color_match.c @@ -33,8 +33,8 @@ int gdImageColorMatch (gdImagePtr im1, gdImagePtr im2) return -4; /* At least 1 color must be allocated */ } - buf = (unsigned long *)safe_emalloc(sizeof(unsigned long), 5 * im2->colorsTotal, 0); - memset( buf, 0, sizeof(unsigned long) * 5 * im2->colorsTotal ); + buf = (unsigned long *)safe_emalloc(sizeof(unsigned long), 5 * gdMaxColors, 0); + memset( buf, 0, sizeof(unsigned long) * 5 * gdMaxColors ); for (x=0; x<im1->sx; x++) { for( y=0; y<im1->sy; y++ ) { diff --git a/ext/gd/libgd/gd_interpolation.c b/ext/gd/libgd/gd_interpolation.c index 2a2479c912..e3cd741f8a 100644 --- a/ext/gd/libgd/gd_interpolation.c +++ b/ext/gd/libgd/gd_interpolation.c @@ -890,8 +890,13 @@ static inline LineContribType * _gdContributionsAlloc(unsigned int line_length, { unsigned int u = 0; LineContribType *res; - int overflow_error = 0; + size_t weights_size; + if (overflow2(windows_size, sizeof(double))) { + return NULL; + } else { + weights_size = windows_size * sizeof(double); + } res = (LineContribType *) gdMalloc(sizeof(LineContribType)); if (!res) { return NULL; @@ -908,15 +913,10 @@ static inline LineContribType * _gdContributionsAlloc(unsigned int line_length, return NULL; } for (u = 0 ; u < line_length ; u++) { - if (overflow2(windows_size, sizeof(double))) { - overflow_error = 1; - } else { - res->ContribRow[u].Weights = (double *) gdMalloc(windows_size * sizeof(double)); - } - if (overflow_error == 1 || res->ContribRow[u].Weights == NULL) { + res->ContribRow[u].Weights = (double *) gdMalloc(weights_size); + if (res->ContribRow[u].Weights == NULL) { unsigned int i; - u--; - for (i=0;i<=u;i++) { + for (i=0;i<u;i++) { gdFree(res->ContribRow[i].Weights); } gdFree(res->ContribRow); diff --git a/ext/gd/tests/bug77269.phpt b/ext/gd/tests/bug77269.phpt new file mode 100644 index 0000000000..c89f674b8a --- /dev/null +++ b/ext/gd/tests/bug77269.phpt @@ -0,0 +1,21 @@ +--TEST-- +Bug #77269 (Potential unsigned underflow in gdImageScale) +--SKIPIF-- +<?php +if (!extension_loaded('gd')) die('skip gd extension not available'); +if (getenv("SKIP_SLOW_TESTS")) die("skip slow test"); +?> +--INI-- +memory_limit=2G +--FILE-- +<?php +$im = imagecreate(2**28, 1); +if(is_resource($im)) { + imagescale($im, 1, 1, IMG_TRIANGLE); +} +?> +===DONE=== +--EXPECTF-- +Warning: imagescale():%S product of memory allocation multiplication would exceed INT_MAX, failing operation gracefully + in %s on line %d +===DONE=== diff --git a/ext/gd/tests/bug77270.phpt b/ext/gd/tests/bug77270.phpt new file mode 100644 index 0000000000..1c4555a64d --- /dev/null +++ b/ext/gd/tests/bug77270.phpt @@ -0,0 +1,18 @@ +--TEST-- +Bug #77270 (imagecolormatch Out Of Bounds Write on Heap) +--SKIPIF-- +<?php +if (!extension_loaded('gd')) die('skip gd extension not available'); +if (!GD_BUNDLED && version_compare(GD_VERSION, '2.2.5', '<=')) die('skip upstream bugfix has not been released'); +?> +--FILE-- +<?php +$img1 = imagecreatetruecolor(0xfff, 0xfff); +$img2 = imagecreate(0xfff, 0xfff); +imagecolorallocate($img2, 0, 0, 0); +imagesetpixel($img2, 0, 0, 255); +imagecolormatch($img1, $img2); +?> +===DONE=== +--EXPECT-- +===DONE=== diff --git a/ext/mbstring/oniguruma/src/regcomp.c b/ext/mbstring/oniguruma/src/regcomp.c index 0e9a9ab38c..3f4c95be6b 100644 --- a/ext/mbstring/oniguruma/src/regcomp.c +++ b/ext/mbstring/oniguruma/src/regcomp.c @@ -469,13 +469,13 @@ compile_length_string_node(Node* node, regex_t* reg) ambig = NSTRING_IS_AMBIG(node); p = prev = sn->s; - prev_len = enclen(enc, p); + SAFE_ENC_LEN(enc, p, sn->end, prev_len); p += prev_len; slen = 1; rlen = 0; for (; p < sn->end; ) { - len = enclen(enc, p); + SAFE_ENC_LEN(enc, p, sn->end, len); if (len == prev_len) { slen++; } @@ -518,12 +518,12 @@ compile_string_node(Node* node, regex_t* reg) ambig = NSTRING_IS_AMBIG(node); p = prev = sn->s; - prev_len = enclen(enc, p); + SAFE_ENC_LEN(enc, p, end, prev_len); p += prev_len; slen = 1; for (; p < end; ) { - len = enclen(enc, p); + SAFE_ENC_LEN(enc, p, end, len); if (len == prev_len) { slen++; } @@ -3435,7 +3435,7 @@ expand_case_fold_string(Node* node, regex_t* reg) goto err; } - len = enclen(reg->enc, p); + SAFE_ENC_LEN(reg->enc, p, end, len); if (n == 0) { if (IS_NULL(snode)) { diff --git a/ext/mbstring/oniguruma/src/regparse.c b/ext/mbstring/oniguruma/src/regparse.c index 8153513202..0c0b07804b 100644 --- a/ext/mbstring/oniguruma/src/regparse.c +++ b/ext/mbstring/oniguruma/src/regparse.c @@ -304,14 +304,17 @@ strdup_with_null(OnigEncoding enc, UChar* s, UChar* end) c = ONIGENC_MBC_TO_CODE(enc, p, end); \ pfetch_prev = p; \ p += ONIGENC_MBC_ENC_LEN(enc, p); \ + if(UNEXPECTED(p > end)) p = end; \ } while (0) #define PINC_S do { \ p += ONIGENC_MBC_ENC_LEN(enc, p); \ + if(UNEXPECTED(p > end)) p = end; \ } while (0) #define PFETCH_S(c) do { \ c = ONIGENC_MBC_TO_CODE(enc, p, end); \ p += ONIGENC_MBC_ENC_LEN(enc, p); \ + if(UNEXPECTED(p > end)) p = end; \ } while (0) #define PPEEK (p < end ? ONIGENC_MBC_TO_CODE(enc, p, end) : PEND_VALUE) @@ -3594,6 +3597,9 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) } else { /* string */ p = tok->backp + enclen(enc, tok->backp); + int len; + SAFE_ENC_LEN(enc, tok->backp, end, len); + p = tok->backp + len; } } break; diff --git a/ext/mbstring/oniguruma/src/regparse.h b/ext/mbstring/oniguruma/src/regparse.h index c9d1fe8a6e..6fc8152aa4 100644 --- a/ext/mbstring/oniguruma/src/regparse.h +++ b/ext/mbstring/oniguruma/src/regparse.h @@ -348,4 +348,16 @@ extern int onig_print_names(FILE*, regex_t*); #endif #endif +#if (defined (__GNUC__) && __GNUC__ > 2 ) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX) +# define UNEXPECTED(condition) __builtin_expect(condition, 0) +#else +# define UNEXPECTED(condition) (condition) +#endif + +#define SAFE_ENC_LEN(enc, p, end, res) do { \ + int __res = enclen(enc, p); \ + if (UNEXPECTED(p + __res > end)) __res = end - p; \ + res = __res; \ +} while(0); + #endif /* REGPARSE_H */ diff --git a/ext/mbstring/tests/bug77370.phpt b/ext/mbstring/tests/bug77370.phpt new file mode 100644 index 0000000000..c4d25582fe --- /dev/null +++ b/ext/mbstring/tests/bug77370.phpt @@ -0,0 +1,13 @@ +--TEST-- +Bug #77370 (Buffer overflow on mb regex functions - fetch_token) +--SKIPIF-- +<?php extension_loaded('mbstring') or die('skip mbstring not available'); ?> +--FILE-- +<?php +var_dump(mb_split(" \xfd","")); +?> +--EXPECT-- +array(1) { + [0]=> + string(0) "" +} diff --git a/ext/mbstring/tests/bug77371.phpt b/ext/mbstring/tests/bug77371.phpt new file mode 100644 index 0000000000..33e5fc115c --- /dev/null +++ b/ext/mbstring/tests/bug77371.phpt @@ -0,0 +1,10 @@ +--TEST-- +Bug #77371 (heap buffer overflow in mb regex functions - compile_string_node) +--SKIPIF-- +<?php extension_loaded('mbstring') or die('skip mbstring not available'); ?> +--FILE-- +<?php +var_dump(mb_ereg("()0\xfc00000\xfc00000\xfc00000\xfc","")); +?> +--EXPECT-- +bool(false)
\ No newline at end of file diff --git a/ext/mbstring/tests/bug77381.phpt b/ext/mbstring/tests/bug77381.phpt new file mode 100644 index 0000000000..cb83759fc0 --- /dev/null +++ b/ext/mbstring/tests/bug77381.phpt @@ -0,0 +1,16 @@ +--TEST-- +Bug #77381 (heap buffer overflow in multibyte match_at) +--SKIPIF-- +<?php extension_loaded('mbstring') or die('skip mbstring not available'); ?> +--FILE-- +<?php +var_dump(mb_ereg("000||0\xfa","0")); +var_dump(mb_ereg("(?i)000000000000000000000\xf0","")); +var_dump(mb_ereg("0000\\"."\xf5","0")); +var_dump(mb_ereg("(?i)FFF00000000000000000\xfd","")); +?> +--EXPECT-- +int(1) +bool(false) +bool(false) +bool(false) diff --git a/ext/phar/phar.c b/ext/phar/phar.c index 90649bd288..5a13ea4369 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -2008,7 +2008,7 @@ next_extension: } while (pos != filename && (*(pos - 1) == '/' || *(pos - 1) == '\0')) { - pos = memchr(pos + 1, '.', filename_len - (pos - filename) + 1); + pos = memchr(pos + 1, '.', filename_len - (pos - filename) - 1); if (!pos) { return FAILURE; } diff --git a/ext/phar/tests/bug77247.phpt b/ext/phar/tests/bug77247.phpt new file mode 100644 index 0000000000..588975f9f2 --- /dev/null +++ b/ext/phar/tests/bug77247.phpt @@ -0,0 +1,14 @@ +--TEST-- +PHP bug #77247 (heap buffer overflow in phar_detect_phar_fname_ext) +--SKIPIF-- +<?php if (!extension_loaded("phar")) die("skip"); ?> +--FILE-- +<?php +try { +var_dump(new Phar('a/.b', 0,'test.phar')); +} catch(UnexpectedValueException $e) { + echo "OK"; +} +?> +--EXPECT-- +OK
\ No newline at end of file diff --git a/ext/standard/dns.c b/ext/standard/dns.c index fb21d6dd77..7d0442230a 100644 --- a/ext/standard/dns.c +++ b/ext/standard/dns.c @@ -456,6 +456,10 @@ static u_char *php_parserr(u_char *cp, u_char *end, querybuf *answer, int type_t GETLONG(ttl, cp); GETSHORT(dlen, cp); CHECKCP(dlen); + if (dlen == 0) { + /* No data in the response - nothing to do */ + return NULL; + } if (type_to_fetch != T_ANY && type != type_to_fetch) { cp += dlen; return cp; @@ -546,6 +550,9 @@ static u_char *php_parserr(u_char *cp, u_char *end, querybuf *answer, int type_t CHECKCP(n); add_assoc_stringl(subarray, "tag", (char*)cp, n); cp += n; + if ( (size_t) dlen < ((size_t)n) + 2 ) { + return NULL; + } n = dlen - n - 2; CHECKCP(n); add_assoc_stringl(subarray, "value", (char*)cp, n); diff --git a/ext/xmlrpc/libxmlrpc/base64.c b/ext/xmlrpc/libxmlrpc/base64.c index dd60dc9cd6..a6410145e2 100644 --- a/ext/xmlrpc/libxmlrpc/base64.c +++ b/ext/xmlrpc/libxmlrpc/base64.c @@ -77,7 +77,7 @@ void base64_encode_xmlrpc(struct buffer_st *b, const char *source, int length) while (!hiteof) { unsigned char igroup[3], ogroup[4]; - int c, n; + int c, n; igroup[0] = igroup[1] = igroup[2] = 0; for (n = 0; n < 3; n++) { @@ -169,7 +169,7 @@ void base64_decode_xmlrpc(struct buffer_st *bfr, const char *source, int length) return; } - if (dtable[c] & 0x80) { + if (dtable[(unsigned char)c] & 0x80) { /* fprintf(stderr, "Offset %i length %i\n", offset, length); fprintf(stderr, "character '%c:%x:%c' in input file.\n", c, c, dtable[c]); diff --git a/ext/xmlrpc/libxmlrpc/xml_element.c b/ext/xmlrpc/libxmlrpc/xml_element.c index 070680d4a7..86aad6108a 100644 --- a/ext/xmlrpc/libxmlrpc/xml_element.c +++ b/ext/xmlrpc/libxmlrpc/xml_element.c @@ -720,6 +720,9 @@ xml_element* xml_elem_parse_buf(const char* in_buf, int len, XML_ELEM_INPUT_OPTI long byte_idx = XML_GetCurrentByteIndex(parser); /* int byte_total = XML_GetCurrentByteCount(parser); */ const char * error_str = XML_ErrorString(err_code); + if(byte_idx > len) { + byte_idx = len; + } if(byte_idx >= 0) { snprintf(buf, sizeof(buf), diff --git a/ext/xmlrpc/tests/bug77242.phpt b/ext/xmlrpc/tests/bug77242.phpt new file mode 100644 index 0000000000..542c06311f --- /dev/null +++ b/ext/xmlrpc/tests/bug77242.phpt @@ -0,0 +1,10 @@ +--TEST-- +Bug #77242 (heap out of bounds read in xmlrpc_decode()) +--SKIPIF-- +<?php if (!extension_loaded("xmlrpc")) print "skip"; ?> +--FILE-- +<?php +var_dump(xmlrpc_decode(base64_decode("PD94bWwgdmVyc2lvbmVuY29kaW5nPSJJU084ODU5NyKkpKSkpKSkpKSkpKSkpKSkpKSkpKSk"))); +?> +--EXPECT-- +NULL
\ No newline at end of file diff --git a/ext/xmlrpc/tests/bug77380.phpt b/ext/xmlrpc/tests/bug77380.phpt new file mode 100644 index 0000000000..8559c07a5a --- /dev/null +++ b/ext/xmlrpc/tests/bug77380.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #77380 (Global out of bounds read in xmlrpc base64 code) +--SKIPIF-- +<?php +if (!extension_loaded("xmlrpc")) print "skip"; +?> +--FILE-- +<?php +var_dump(xmlrpc_decode(base64_decode("PGJhc2U2ND7CkzwvYmFzZTY0Pgo="))); +?> +--EXPECT-- +object(stdClass)#1 (2) { + ["scalar"]=> + string(0) "" + ["xmlrpc_type"]=> + string(6) "base64" +} |