From: Nikita Popov Date: Mon, 12 Oct 2015 20:05:19 +0000 (+0200) Subject: Fixed bug #70430 X-Git-Tag: php-7.0.1RC1~235 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e3e92e96c158c4fc294ead36f9d73941bdbf679e;p=php Fixed bug #70430 --- diff --git a/NEWS b/NEWS index 55f82f022c..e7ff52a53f 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,7 @@ PHP NEWS - Core: . Fixed bug #70689 (Exception handler does not work as expected). (Laruence) + . Fixed bug #70430 (Stack buffer overflow in zend_language_parser()). (Nikita) - SOAP: . Fixed bug #70715 (Segmentation fault inside soap client). (Laruence) diff --git a/Zend/tests/bug70430.phpt b/Zend/tests/bug70430.phpt new file mode 100644 index 0000000000..59983653e9 --- /dev/null +++ b/Zend/tests/bug70430.phpt @@ -0,0 +1,10 @@ +--TEST-- +Bug #70430: Stack buffer overflow in zend_language_parser() +--FILE-- + +--EXPECTF-- +Parse error: syntax error, unexpected '"*** Testing function() : ***' (T_CONSTANT_ENCAPSED_STRING), expecting variable (T_VARIABLE) or '{' or '$' in %s on line %d diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index a253a76eff..3fc6494702 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -1278,20 +1278,30 @@ isset_variable: would have been. */ static YYSIZE_T zend_yytnamerr(char *yyres, const char *yystr) { - if (!yyres) { - return yystrlen(yystr); + /* CG(parse_error) states: + * 0 => yyres = NULL, yystr is the unexpected token + * 1 => yyres = NULL, yystr is one of the expected tokens + * 2 => yyres != NULL, yystr is the unexpected token + * 3 => yyres != NULL, yystr is one of the expected tokens + */ + if (yyres && CG(parse_error) < 2) { + CG(parse_error) = 2; } - if (CG(parse_error) == 0) { + + if (CG(parse_error) % 2 == 0) { + /* The unexpected token */ char buffer[120]; const unsigned char *end, *str, *tok1 = NULL, *tok2 = NULL; unsigned int len = 0, toklen = 0, yystr_len; - CG(parse_error) = 1; + CG(parse_error)++; if (LANG_SCNG(yy_text)[0] == 0 && LANG_SCNG(yy_leng) == 1 && memcmp(yystr, "\"end of file\"", sizeof("\"end of file\"") - 1) == 0) { - yystpcpy(yyres, "end of file"); + if (yyres) { + yystpcpy(yyres, "end of file"); + } return sizeof("end of file")-1; } @@ -1312,14 +1322,22 @@ static YYSIZE_T zend_yytnamerr(char *yyres, const char *yystr) } else { len = (end - str) > 30 ? 30 : (end - str); } - if (toklen) { - snprintf(buffer, sizeof(buffer), "'%.*s' %.*s", len, str, toklen, tok1); - } else { - snprintf(buffer, sizeof(buffer), "'%.*s'", len, str); + if (yyres) { + if (toklen) { + snprintf(buffer, sizeof(buffer), "'%.*s' %.*s", len, str, toklen, tok1); + } else { + snprintf(buffer, sizeof(buffer), "'%.*s'", len, str); + } + yystpcpy(yyres, buffer); } - yystpcpy(yyres, buffer); return len + (toklen ? toklen + 1 : 0) + 2; } + + /* One of the expected tokens */ + if (!yyres) { + return yystrlen(yystr) - (*yystr == '"' ? 2 : 0); + } + if (*yystr == '"') { YYSIZE_T yyn = 0; const char *yyp = yystr;