]> granicus.if.org Git - php/commitdiff
Fixed bug #70430
authorNikita Popov <nikic@php.net>
Mon, 12 Oct 2015 20:05:19 +0000 (22:05 +0200)
committerNikita Popov <nikic@php.net>
Thu, 15 Oct 2015 20:14:23 +0000 (22:14 +0200)
NEWS
Zend/tests/bug70430.phpt [new file with mode: 0644]
Zend/zend_language_parser.y

diff --git a/NEWS b/NEWS
index 55f82f022c97d5810befe2bf4e01e8d19d2a0e14..e7ff52a53fa276b48f0787b350ed67065c7b31ed 100644 (file)
--- 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 (file)
index 0000000..5998365
--- /dev/null
@@ -0,0 +1,10 @@
+--TEST--
+Bug #70430: Stack buffer overflow in zend_language_parser()
+--FILE--
+<?php
+
+$"*** Testing function() :  ***\n";
+
+?>
+--EXPECTF--
+Parse error: syntax error, unexpected '"*** Testing function() :  ***' (T_CONSTANT_ENCAPSED_STRING), expecting variable (T_VARIABLE) or '{' or '$' in %s on line %d
index a253a76eff982b4c0850392f0819ee341c23125f..3fc64947020f21f227fe79a45c6b5dd1022d035f 100644 (file)
@@ -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;