From: Stanislav Malyshev Date: Fri, 23 Mar 2007 20:34:11 +0000 (+0000) Subject: MFB: fix MOPB-29 - unserialize modifier S does not calculate length correctly X-Git-Tag: RELEASE_1_1_0~132 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=638a8c9e070c246f954f427e3e2e5e6ebe01a9f7;p=php MFB: fix MOPB-29 - unserialize modifier S does not calculate length correctly --- diff --git a/ext/standard/tests/serialize/unserializeS.phpt b/ext/standard/tests/serialize/unserializeS.phpt new file mode 100755 index 0000000000..8516f7183e --- /dev/null +++ b/ext/standard/tests/serialize/unserializeS.phpt @@ -0,0 +1,14 @@ +--TEST-- +Bug MOPB-29 (wrong length calculation for S) +--INI-- +error_reporting=0 +--FILE-- +1,str_repeat('"', 200)."2"=>1); + +$data = unserialize($str); +var_dump($data); + +--EXPECT-- +string(100) "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c index 066f5351ed..38fa26a961 100644 --- a/ext/standard/var_unserializer.c +++ b/ext/standard/var_unserializer.c @@ -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; diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index 10fac4c4be..d4bf0f0a8b 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -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; }