]> granicus.if.org Git - php/commitdiff
MFB: fix MOPB-29 - unserialize modifier S does not calculate length correctly
authorStanislav Malyshev <stas@php.net>
Fri, 23 Mar 2007 20:34:11 +0000 (20:34 +0000)
committerStanislav Malyshev <stas@php.net>
Fri, 23 Mar 2007 20:34:11 +0000 (20:34 +0000)
ext/standard/tests/serialize/unserializeS.phpt [new file with mode: 0755]
ext/standard/var_unserializer.c
ext/standard/var_unserializer.re

diff --git a/ext/standard/tests/serialize/unserializeS.phpt b/ext/standard/tests/serialize/unserializeS.phpt
new file mode 100755 (executable)
index 0000000..8516f71
--- /dev/null
@@ -0,0 +1,14 @@
+--TEST--
+Bug MOPB-29 (wrong length calculation for S)
+--INI--
+error_reporting=0
+--FILE--
+<?php
+$str = 'S:'.(100*3).':"'.str_repeat('\61', 100).'"';
+$arr = array(str_repeat('"', 200)."1"=>1,str_repeat('"', 200)."2"=>1);
+
+$data = unserialize($str);
+var_dump($data);
+
+--EXPECT--
+string(100) "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
index 066f5351ed42715e69bb43a326cebb0e47dfd8fd..38fa26a96195d2dee51687b1ed32ada04d4497a6 100644 (file)
@@ -1,10 +1,10 @@
-/* Generated by re2c 0.10.2 on Thu Dec 21 19:19:25 2007 */
+/* Generated by re2c 0.11.2 on Fri Mar 23 13:33:19 2007 */
 #line 1 "ext/standard/var_unserializer.re"
 /*
   +----------------------------------------------------------------------+
   | PHP Version 5                                                        |
   +----------------------------------------------------------------------+
-  | Copyright (c) 1997-2007 The PHP Group                                |
+  | Copyright (c) 1997-2006 The PHP Group                                |
   +----------------------------------------------------------------------+
   | This source file is subject to version 3.01 of the PHP license,      |
   | that is bundled with this package in the file LICENSE, and is        |
@@ -112,12 +112,18 @@ static UChar *unserialize_ustr(const unsigned char **p, int len)
        return ustr;
 }
 
-static char *unserialize_str(const unsigned char **p, int len)
+static char *unserialize_str(const unsigned char **p, int *len)
 {
-       int i, j;
-       char *str = emalloc(len+1);
+       size_t i, j;
+       char *str = safe_emalloc(*len, 1, 1);
+       unsigned char *end = *p+*len;
 
-       for (i = 0; i < len; i++) {
+       if(end < *p) {
+               efree(str);
+               return NULL;
+       }
+
+       for (i = 0; i < *len && *p < end; i++) {
                if (**p != '\\') {
                        str[i] = (char)**p;
                } else {
@@ -141,6 +147,7 @@ static char *unserialize_str(const unsigned char **p, int len)
                (*p)++;
        }
        str[i] = 0;
+       *len = i;
        return str;
 }
 
@@ -211,7 +218,7 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
 #define YYMARKER marker
 
 
-#line 219 "ext/standard/var_unserializer.re"
+#line 226 "ext/standard/var_unserializer.re"
 
 
 
@@ -439,7 +446,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
        
        
 {
-       static unsigned char yybm[] = {
+       static const unsigned char yybm[] = {
                  0,   0,   0,   0,   0,   0,   0,   0, 
                  0,   0,   0,   0,   0,   0,   0,   0, 
                  0,   0,   0,   0,   0,   0,   0,   0, 
@@ -474,13 +481,13 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
                  0,   0,   0,   0,   0,   0,   0,   0, 
        };
 
-#line 478 "ext/standard/var_unserializer.c"
+#line 485 "ext/standard/var_unserializer.c"
        {
                YYCTYPE yych;
 
                if((YYLIMIT - YYCURSOR) < 7) YYFILL(7);
                yych = *YYCURSOR;
-               switch(yych){
+               switch(yych) {
                case 'C':
                case 'O':       goto yy14;
                case 'N':       goto yy5;
@@ -501,9 +508,9 @@ yy2:
                yych = *(YYMARKER = ++YYCURSOR);
                if(yych == ':') goto yy103;
 yy3:
-#line 769 "ext/standard/var_unserializer.re"
+#line 776 "ext/standard/var_unserializer.re"
                { return 0; }
-#line 507 "ext/standard/var_unserializer.c"
+#line 514 "ext/standard/var_unserializer.c"
 yy4:
                yych = *(YYMARKER = ++YYCURSOR);
                if(yych == ':') goto yy97;
@@ -550,13 +557,13 @@ yy14:
                goto yy3;
 yy15:
                ++YYCURSOR;
-#line 763 "ext/standard/var_unserializer.re"
+#line 770 "ext/standard/var_unserializer.re"
                {
        /* this is the case where we have less data than planned */
        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data");
        return 0; /* not sure if it should be 0 or 1 here? */
 }
-#line 560 "ext/standard/var_unserializer.c"
+#line 567 "ext/standard/var_unserializer.c"
 yy17:
                yych = *++YYCURSOR;
                goto yy3;
@@ -586,7 +593,7 @@ yy21:
                yych = *++YYCURSOR;
                if(yych != '"') goto yy19;
                ++YYCURSOR;
-#line 650 "ext/standard/var_unserializer.re"
+#line 657 "ext/standard/var_unserializer.re"
                {
        size_t len, len2, len3, maxlen;
        long elements;
@@ -699,7 +706,7 @@ yy21:
 
        return object_common2(UNSERIALIZE_PASSTHRU, elements);
 }
-#line 703 "ext/standard/var_unserializer.c"
+#line 710 "ext/standard/var_unserializer.c"
 yy26:
                yych = *++YYCURSOR;
                if(yych <= ',') {
@@ -724,7 +731,7 @@ yy28:
                yych = *++YYCURSOR;
                if(yych != '"') goto yy19;
                ++YYCURSOR;
-#line 642 "ext/standard/var_unserializer.re"
+#line 649 "ext/standard/var_unserializer.re"
                {
 
        INIT_PZVAL(*rval);
@@ -732,7 +739,7 @@ yy28:
        return object_common2(UNSERIALIZE_PASSTHRU,
                        object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
 }
-#line 736 "ext/standard/var_unserializer.c"
+#line 743 "ext/standard/var_unserializer.c"
 yy33:
                yych = *++YYCURSOR;
                if(yych == '+') goto yy34;
@@ -753,7 +760,7 @@ yy35:
                yych = *++YYCURSOR;
                if(yych != '{') goto yy19;
                ++YYCURSOR;
-#line 620 "ext/standard/var_unserializer.re"
+#line 627 "ext/standard/var_unserializer.re"
                {
        long elements = parse_iv(start + 2);
        /* use iv() not uiv() in order to check data range */
@@ -775,7 +782,7 @@ yy35:
 
        return finish_nested_data(UNSERIALIZE_PASSTHRU);
 }
-#line 779 "ext/standard/var_unserializer.c"
+#line 786 "ext/standard/var_unserializer.c"
 yy40:
                yych = *++YYCURSOR;
                if(yych == '+') goto yy41;
@@ -796,7 +803,7 @@ yy42:
                yych = *++YYCURSOR;
                if(yych != '"') goto yy19;
                ++YYCURSOR;
-#line 591 "ext/standard/var_unserializer.re"
+#line 598 "ext/standard/var_unserializer.re"
                {
        size_t len, maxlen;
        UChar *ustr;
@@ -825,7 +832,7 @@ yy42:
        ZVAL_UNICODEL(*rval, ustr, len, 0);
        return 1;
 }
-#line 829 "ext/standard/var_unserializer.c"
+#line 836 "ext/standard/var_unserializer.c"
 yy47:
                yych = *++YYCURSOR;
                if(yych == '+') goto yy48;
@@ -846,7 +853,7 @@ yy49:
                yych = *++YYCURSOR;
                if(yych != '"') goto yy19;
                ++YYCURSOR;
-#line 562 "ext/standard/var_unserializer.re"
+#line 569 "ext/standard/var_unserializer.re"
                {
        size_t len, maxlen;
        char *str;
@@ -858,7 +865,7 @@ yy49:
                return 0;
        }
 
-       if ((str = unserialize_str(&YYCURSOR, len)) == NULL) {
+       if ((str = unserialize_str(&YYCURSOR, &len)) == NULL) {
                return 0;
        }
 
@@ -875,7 +882,7 @@ yy49:
        ZVAL_STRINGL(*rval, str, len, 0);
        return 1;
 }
-#line 879 "ext/standard/var_unserializer.c"
+#line 886 "ext/standard/var_unserializer.c"
 yy54:
                yych = *++YYCURSOR;
                if(yych == '+') goto yy55;
@@ -896,7 +903,7 @@ yy56:
                yych = *++YYCURSOR;
                if(yych != '"') goto yy19;
                ++YYCURSOR;
-#line 534 "ext/standard/var_unserializer.re"
+#line 541 "ext/standard/var_unserializer.re"
                {
        size_t len, maxlen;
        char *str;
@@ -924,7 +931,7 @@ yy56:
        ZVAL_STRINGL(*rval, str, len, 1);
        return 1;
 }
-#line 928 "ext/standard/var_unserializer.c"
+#line 935 "ext/standard/var_unserializer.c"
 yy61:
                yych = *++YYCURSOR;
                if(yych <= '/') {
@@ -1012,14 +1019,14 @@ yy69:
                }
 yy71:
                ++YYCURSOR;
-#line 527 "ext/standard/var_unserializer.re"
+#line 534 "ext/standard/var_unserializer.re"
                {
        *p = YYCURSOR;
        INIT_PZVAL(*rval);
        ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL));
        return 1;
 }
-#line 1023 "ext/standard/var_unserializer.c"
+#line 1030 "ext/standard/var_unserializer.c"
 yy73:
                yych = *++YYCURSOR;
                if(yych <= ',') {
@@ -1078,7 +1085,7 @@ yy81:
                yych = *++YYCURSOR;
                if(yych != ';') goto yy19;
                ++YYCURSOR;
-#line 512 "ext/standard/var_unserializer.re"
+#line 519 "ext/standard/var_unserializer.re"
                {
        *p = YYCURSOR;
        INIT_PZVAL(*rval);
@@ -1093,7 +1100,7 @@ yy81:
 
        return 1;
 }
-#line 1097 "ext/standard/var_unserializer.c"
+#line 1104 "ext/standard/var_unserializer.c"
 yy84:
                yych = *++YYCURSOR;
                if(yych == 'N') goto yy81;
@@ -1120,14 +1127,14 @@ yy87:
                if(yych <= '9') goto yy87;
                if(yych != ';') goto yy19;
                ++YYCURSOR;
-#line 505 "ext/standard/var_unserializer.re"
+#line 512 "ext/standard/var_unserializer.re"
                {
        *p = YYCURSOR;
        INIT_PZVAL(*rval);
        ZVAL_LONG(*rval, parse_iv(start + 2));
        return 1;
 }
-#line 1131 "ext/standard/var_unserializer.c"
+#line 1138 "ext/standard/var_unserializer.c"
 yy91:
                yych = *++YYCURSOR;
                if(yych <= '/') goto yy19;
@@ -1135,24 +1142,24 @@ yy91:
                yych = *++YYCURSOR;
                if(yych != ';') goto yy19;
                ++YYCURSOR;
-#line 498 "ext/standard/var_unserializer.re"
+#line 505 "ext/standard/var_unserializer.re"
                {
        *p = YYCURSOR;
        INIT_PZVAL(*rval);
        ZVAL_BOOL(*rval, parse_iv(start + 2));
        return 1;
 }
-#line 1146 "ext/standard/var_unserializer.c"
+#line 1153 "ext/standard/var_unserializer.c"
 yy95:
                ++YYCURSOR;
-#line 491 "ext/standard/var_unserializer.re"
+#line 498 "ext/standard/var_unserializer.re"
                {
        *p = YYCURSOR;
        INIT_PZVAL(*rval);
        ZVAL_NULL(*rval);
        return 1;
 }
-#line 1156 "ext/standard/var_unserializer.c"
+#line 1163 "ext/standard/var_unserializer.c"
 yy97:
                yych = *++YYCURSOR;
                if(yych <= ',') {
@@ -1175,7 +1182,7 @@ yy99:
                if(yych <= '9') goto yy99;
                if(yych != ';') goto yy19;
                ++YYCURSOR;
-#line 468 "ext/standard/var_unserializer.re"
+#line 475 "ext/standard/var_unserializer.re"
                {
        long id;
 
@@ -1198,7 +1205,7 @@ yy99:
        
        return 1;
 }
-#line 1202 "ext/standard/var_unserializer.c"
+#line 1209 "ext/standard/var_unserializer.c"
 yy103:
                yych = *++YYCURSOR;
                if(yych <= ',') {
@@ -1221,7 +1228,7 @@ yy105:
                if(yych <= '9') goto yy105;
                if(yych != ';') goto yy19;
                ++YYCURSOR;
-#line 447 "ext/standard/var_unserializer.re"
+#line 454 "ext/standard/var_unserializer.re"
                {
        long id;
 
@@ -1242,10 +1249,10 @@ yy105:
        
        return 1;
 }
-#line 1246 "ext/standard/var_unserializer.c"
+#line 1253 "ext/standard/var_unserializer.c"
        }
 }
-#line 771 "ext/standard/var_unserializer.re"
+#line 778 "ext/standard/var_unserializer.re"
 
 
        return 0;
index 10fac4c4bedc5a6025fa2d47f94257faf0f1b9df..d4bf0f0a8b8f2186e8ee5c703b55f3247ee8bc60 100644 (file)
@@ -110,12 +110,18 @@ static UChar *unserialize_ustr(const unsigned char **p, int len)
        return ustr;
 }
 
-static char *unserialize_str(const unsigned char **p, int len)
+static char *unserialize_str(const unsigned char **p, int *len)
 {
-       int i, j;
-       char *str = emalloc(len+1);
+       size_t i, j;
+       char *str = safe_emalloc(*len, 1, 1);
+       unsigned char *end = *p+*len;
 
-       for (i = 0; i < len; i++) {
+       if(end < *p) {
+               efree(str);
+               return NULL;
+       }
+
+       for (i = 0; i < *len && *p < end; i++) {
                if (**p != '\\') {
                        str[i] = (char)**p;
                } else {
@@ -139,6 +145,7 @@ static char *unserialize_str(const unsigned char **p, int len)
                (*p)++;
        }
        str[i] = 0;
+       *len = i;
        return str;
 }
 
@@ -570,7 +577,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
                return 0;
        }
 
-       if ((str = unserialize_str(&YYCURSOR, len)) == NULL) {
+       if ((str = unserialize_str(&YYCURSOR, &len)) == NULL) {
                return 0;
        }