From: Stanislav Malyshev Date: Sun, 28 Apr 2002 16:56:33 +0000 (+0000) Subject: Fix couple of nasty serializer bugs: X-Git-Tag: php-4.3.0dev-ZendEngine2-Preview1~381 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a57381e3bd1cbb2c5d75e2a456422301399a33fe;p=php Fix couple of nasty serializer bugs: a) When array unserializer encounters less data than it expects (like: a:1:{}) it crashes. I don't understand exactly why it does, but the fact is it does. So now it should catch "}" and bail out. b) When array/object data are serialized, the count is written by hash count. However, it can be that in-loop check fails and less data than expected will then be written into the array. Which, due to a), would crash on unserialize. So now it will write empty entries in place of entries it cannot serialize (the other choice would be make two passes on the data, which I don't like). --- diff --git a/ext/standard/var.c b/ext/standard/var.c index 4b8e661aae..0f88fae366 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -466,6 +466,9 @@ static void php_var_serialize_class(smart_str *buf, zval **struc, zval *retval_p php_error(E_NOTICE, "__sleep should return an array only " "containing the names of instance-variables to " "serialize."); + /* we should still add element even if it's not OK, + since we already wrote the length of the array before */ + smart_str_appendl(buf,"s:0:\"\";N;", 9); continue; } @@ -579,12 +582,6 @@ static void php_var_serialize_intern(smart_str *buf, zval **struc, HashTable *va if (i == HASH_KEY_NON_EXISTANT) break; - if (zend_hash_get_current_data_ex(myht, - (void **) &data, &pos) != SUCCESS - || !data - || data == struc) - continue; - switch (i) { case HASH_KEY_IS_LONG: php_var_serialize_long(buf, index); @@ -593,7 +590,17 @@ static void php_var_serialize_intern(smart_str *buf, zval **struc, HashTable *va php_var_serialize_string(buf, key, key_len - 1); break; } - php_var_serialize_intern(buf, data, var_hash TSRMLS_CC); + + /* we should still add element even if it's not OK, + since we already wrote the length of the array before */ + if (zend_hash_get_current_data_ex(myht, + (void **) &data, &pos) != SUCCESS + || !data + || data == struc) { + smart_str_appendl(buf, "N;", 2); + } else { + php_var_serialize_intern(buf, data, var_hash TSRMLS_CC); + } } } smart_str_appendc(buf, '}'); diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c index eec27d0f82..bf0478d85d 100644 --- a/ext/standard/var_unserializer.c +++ b/ext/standard/var_unserializer.c @@ -1,5 +1,5 @@ -/* Generated by re2c 0.5 on Tue Nov 27 00:35:25 2001 */ -#line 1 "/usr/src/web/php/php4/ext/standard/var_unserializer.re" +/* Generated by re2c 0.5 on Sun Apr 28 19:47:31 2002 */ +#line 1 "var_unserializer.re" #include "php.h" #include "ext/standard/php_var.h" #include "php_incomplete_class.h" @@ -272,34 +272,42 @@ yy1: ++YYCURSOR; yy0: if((YYLIMIT - YYCURSOR) < 5) YYFILL(5); yych = *YYCURSOR; - if(yych <= 'c'){ - if(yych <= 'Q'){ - if(yych <= 'M') goto yy13; - if(yych <= 'N') goto yy5; - if(yych <= 'O') goto yy12; - goto yy13; + if(yych <= 'd'){ + if(yych <= 'R'){ + if(yych <= 'N'){ + if(yych <= 'M') goto yy15; + goto yy5; + } else { + if(yych <= 'O') goto yy12; + if(yych <= 'Q') goto yy15; + goto yy3; + } } else { - if(yych <= '`'){ - if(yych <= 'R') goto yy3; - goto yy13; + if(yych <= 'a'){ + if(yych <= '`') goto yy15; + goto yy10; } else { - if(yych <= 'a') goto yy10; if(yych <= 'b') goto yy6; - goto yy13; + if(yych <= 'c') goto yy15; + goto yy8; } } } else { - if(yych <= 'n'){ - if(yych <= 'd') goto yy8; - if(yych == 'i') goto yy7; - goto yy13; - } else { - if(yych <= 'r'){ - if(yych <= 'o') goto yy11; - goto yy13; + if(yych <= 'r'){ + if(yych <= 'i'){ + if(yych <= 'h') goto yy15; + goto yy7; } else { + if(yych == 'o') goto yy11; + goto yy15; + } + } else { + if(yych <= '|'){ if(yych <= 's') goto yy9; - if(yych <= '\277') goto yy13; + goto yy15; + } else { + if(yych <= '}') goto yy13; + if(yych <= '\277') goto yy15; } } } @@ -309,60 +317,68 @@ yy2: YYCURSOR = YYMARKER; } yy3: yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); - if(yych == ':') goto yy73; + if(yych == ':') goto yy75; yy4: -#line 397 +#line 404 { return 0; } yy5: yych = *++YYCURSOR; - if(yych == ';') goto yy71; + if(yych == ';') goto yy73; goto yy4; yy6: yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); - if(yych == ':') goto yy65; + if(yych == ':') goto yy67; goto yy4; yy7: yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); - if(yych == ':') goto yy59; + if(yych == ':') goto yy61; goto yy4; yy8: yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); - if(yych == ':') goto yy42; + if(yych == ':') goto yy44; goto yy4; yy9: yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); - if(yych == ':') goto yy35; + if(yych == ':') goto yy37; goto yy4; yy10: yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); - if(yych == ':') goto yy28; + if(yych == ':') goto yy30; goto yy4; yy11: yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); - if(yych == ':') goto yy21; + if(yych == ':') goto yy23; goto yy4; yy12: yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); - if(yych == ':') goto yy14; + if(yych == ':') goto yy16; goto yy4; yy13: yych = *++YYCURSOR; +yy14: +#line 398 + { + /* this is the case where we have less data than planned */ + zend_error(E_NOTICE, "Unexpected end of serialized data"); + return 0; /* not sure if it should be 0 or 1 here? */ +} +yy15: yych = *++YYCURSOR; goto yy4; -yy14: yych = *++YYCURSOR; - if(yybm[0+yych] & 128) goto yy16; - if(yych == '+') goto yy15; +yy16: yych = *++YYCURSOR; + if(yybm[0+yych] & 128) goto yy18; + if(yych == '+') goto yy17; if(yych != '-') goto yy2; -yy15: yych = *++YYCURSOR; - if(yybm[0+yych] & 128) goto yy16; +yy17: yych = *++YYCURSOR; + if(yybm[0+yych] & 128) goto yy18; goto yy2; -yy16: ++YYCURSOR; +yy18: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; -yy17: if(yybm[0+yych] & 128) goto yy16; +yy19: if(yybm[0+yych] & 128) goto yy18; if(yych != ':') goto yy2; -yy18: yych = *++YYCURSOR; +yy20: yych = *++YYCURSOR; if(yych != '"') goto yy2; -yy19: yych = *++YYCURSOR; -yy20: -#line 329 +yy21: yych = *++YYCURSOR; +yy22: +#line 330 { int len; int elements; @@ -419,7 +435,7 @@ yy20: } } else efree(class_name); - + *p = YYCURSOR; elements = object_common1(UNSERIALIZE_PASSTHRU, ce); @@ -430,29 +446,29 @@ yy20: return object_common2(UNSERIALIZE_PASSTHRU, elements); } -yy21: yych = *++YYCURSOR; +yy23: yych = *++YYCURSOR; if(yych <= ','){ if(yych != '+') goto yy2; } else { - if(yych <= '-') goto yy22; + if(yych <= '-') goto yy24; if(yych <= '/') goto yy2; - if(yych <= '9') goto yy23; + if(yych <= '9') goto yy25; goto yy2; } -yy22: yych = *++YYCURSOR; +yy24: yych = *++YYCURSOR; if(yych <= '/') goto yy2; if(yych >= ':') goto yy2; -yy23: ++YYCURSOR; +yy25: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; -yy24: if(yych <= '/') goto yy2; - if(yych <= '9') goto yy23; +yy26: if(yych <= '/') goto yy2; + if(yych <= '9') goto yy25; if(yych >= ';') goto yy2; -yy25: yych = *++YYCURSOR; +yy27: yych = *++YYCURSOR; if(yych != '"') goto yy2; -yy26: yych = *++YYCURSOR; -yy27: -#line 321 +yy28: yych = *++YYCURSOR; +yy29: +#line 322 { INIT_PZVAL(*rval); @@ -460,29 +476,29 @@ yy27: return object_common2(UNSERIALIZE_PASSTHRU, object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR)); } -yy28: yych = *++YYCURSOR; +yy30: yych = *++YYCURSOR; if(yych <= ','){ if(yych != '+') goto yy2; } else { - if(yych <= '-') goto yy29; + if(yych <= '-') goto yy31; if(yych <= '/') goto yy2; - if(yych <= '9') goto yy30; + if(yych <= '9') goto yy32; goto yy2; } -yy29: yych = *++YYCURSOR; +yy31: yych = *++YYCURSOR; if(yych <= '/') goto yy2; if(yych >= ':') goto yy2; -yy30: ++YYCURSOR; +yy32: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; -yy31: if(yych <= '/') goto yy2; - if(yych <= '9') goto yy30; +yy33: if(yych <= '/') goto yy2; + if(yych <= '9') goto yy32; if(yych >= ';') goto yy2; -yy32: yych = *++YYCURSOR; +yy34: yych = *++YYCURSOR; if(yych != '{') goto yy2; -yy33: yych = *++YYCURSOR; -yy34: -#line 303 +yy35: yych = *++YYCURSOR; +yy36: +#line 304 { int elements = parse_iv(start + 2); @@ -500,29 +516,29 @@ yy34: return finish_nested_data(UNSERIALIZE_PASSTHRU); } -yy35: yych = *++YYCURSOR; +yy37: yych = *++YYCURSOR; if(yych <= ','){ if(yych != '+') goto yy2; } else { - if(yych <= '-') goto yy36; + if(yych <= '-') goto yy38; if(yych <= '/') goto yy2; - if(yych <= '9') goto yy37; + if(yych <= '9') goto yy39; goto yy2; } -yy36: yych = *++YYCURSOR; +yy38: yych = *++YYCURSOR; if(yych <= '/') goto yy2; if(yych >= ':') goto yy2; -yy37: ++YYCURSOR; +yy39: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; -yy38: if(yych <= '/') goto yy2; - if(yych <= '9') goto yy37; +yy40: if(yych <= '/') goto yy2; + if(yych <= '9') goto yy39; if(yych >= ';') goto yy2; -yy39: yych = *++YYCURSOR; +yy41: yych = *++YYCURSOR; if(yych != '"') goto yy2; -yy40: yych = *++YYCURSOR; -yy41: -#line 283 +yy42: yych = *++YYCURSOR; +yy43: +#line 284 { int len; char *str; @@ -542,192 +558,192 @@ yy41: ZVAL_STRINGL(*rval, str, len, 0); return 1; } -yy42: yych = *++YYCURSOR; +yy44: yych = *++YYCURSOR; if(yych <= '-'){ - if(yych == '+') goto yy43; + if(yych == '+') goto yy45; if(yych <= ',') goto yy2; } else { - if(yych <= '.') goto yy46; + if(yych <= '.') goto yy48; if(yych <= '/') goto yy2; - if(yych <= '9') goto yy44; + if(yych <= '9') goto yy46; goto yy2; } -yy43: yych = *++YYCURSOR; - if(yych == '.') goto yy46; +yy45: yych = *++YYCURSOR; + if(yych == '.') goto yy48; if(yych <= '/') goto yy2; if(yych >= ':') goto yy2; -yy44: ++YYCURSOR; +yy46: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; -yy45: if(yych <= '/'){ - if(yych == '.') goto yy56; +yy47: if(yych <= '/'){ + if(yych == '.') goto yy58; goto yy2; } else { - if(yych <= '9') goto yy44; - if(yych == ';') goto yy49; + if(yych <= '9') goto yy46; + if(yych == ';') goto yy51; goto yy2; } -yy46: yych = *++YYCURSOR; +yy48: yych = *++YYCURSOR; if(yych <= '/') goto yy2; if(yych >= ':') goto yy2; -yy47: ++YYCURSOR; +yy49: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; -yy48: if(yych <= ';'){ +yy50: if(yych <= ';'){ if(yych <= '/') goto yy2; - if(yych <= '9') goto yy47; + if(yych <= '9') goto yy49; if(yych <= ':') goto yy2; } else { if(yych <= 'E'){ if(yych <= 'D') goto yy2; - goto yy51; + goto yy53; } else { - if(yych == 'e') goto yy51; + if(yych == 'e') goto yy53; goto yy2; } } -yy49: yych = *++YYCURSOR; -yy50: -#line 276 +yy51: yych = *++YYCURSOR; +yy52: +#line 277 { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_DOUBLE(*rval, atof(start + 2)); return 1; } -yy51: yych = *++YYCURSOR; +yy53: yych = *++YYCURSOR; if(yych <= ','){ if(yych != '+') goto yy2; } else { - if(yych <= '-') goto yy52; + if(yych <= '-') goto yy54; if(yych <= '/') goto yy2; - if(yych <= '9') goto yy53; + if(yych <= '9') goto yy55; goto yy2; } -yy52: yych = *++YYCURSOR; +yy54: yych = *++YYCURSOR; if(yych <= ','){ - if(yych == '+') goto yy55; + if(yych == '+') goto yy57; goto yy2; } else { - if(yych <= '-') goto yy55; + if(yych <= '-') goto yy57; if(yych <= '/') goto yy2; if(yych >= ':') goto yy2; } -yy53: ++YYCURSOR; +yy55: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; -yy54: if(yych <= '/') goto yy2; - if(yych <= '9') goto yy53; - if(yych == ';') goto yy49; +yy56: if(yych <= '/') goto yy2; + if(yych <= '9') goto yy55; + if(yych == ';') goto yy51; goto yy2; -yy55: yych = *++YYCURSOR; +yy57: yych = *++YYCURSOR; if(yych <= '/') goto yy2; - if(yych <= '9') goto yy53; + if(yych <= '9') goto yy55; goto yy2; -yy56: yych = *++YYCURSOR; +yy58: yych = *++YYCURSOR; if(yych <= '/') goto yy2; if(yych >= ':') goto yy2; -yy57: ++YYCURSOR; +yy59: ++YYCURSOR; if((YYLIMIT - YYCURSOR) < 4) YYFILL(4); yych = *YYCURSOR; -yy58: if(yych <= ';'){ +yy60: if(yych <= ';'){ if(yych <= '/') goto yy2; - if(yych <= '9') goto yy57; + if(yych <= '9') goto yy59; if(yych <= ':') goto yy2; - goto yy49; + goto yy51; } else { if(yych <= 'E'){ if(yych <= 'D') goto yy2; - goto yy51; + goto yy53; } else { - if(yych == 'e') goto yy51; + if(yych == 'e') goto yy53; goto yy2; } } -yy59: yych = *++YYCURSOR; +yy61: yych = *++YYCURSOR; if(yych <= ','){ if(yych != '+') goto yy2; } else { - if(yych <= '-') goto yy60; + if(yych <= '-') goto yy62; if(yych <= '/') goto yy2; - if(yych <= '9') goto yy61; + if(yych <= '9') goto yy63; goto yy2; } -yy60: yych = *++YYCURSOR; +yy62: yych = *++YYCURSOR; if(yych <= '/') goto yy2; if(yych >= ':') goto yy2; -yy61: ++YYCURSOR; +yy63: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; -yy62: if(yych <= '/') goto yy2; - if(yych <= '9') goto yy61; +yy64: if(yych <= '/') goto yy2; + if(yych <= '9') goto yy63; if(yych != ';') goto yy2; -yy63: yych = *++YYCURSOR; -yy64: -#line 269 +yy65: yych = *++YYCURSOR; +yy66: +#line 270 { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_LONG(*rval, parse_iv(start + 2)); return 1; } -yy65: yych = *++YYCURSOR; +yy67: yych = *++YYCURSOR; if(yych <= ','){ if(yych != '+') goto yy2; } else { - if(yych <= '-') goto yy66; + if(yych <= '-') goto yy68; if(yych <= '/') goto yy2; - if(yych <= '9') goto yy67; + if(yych <= '9') goto yy69; goto yy2; } -yy66: yych = *++YYCURSOR; +yy68: yych = *++YYCURSOR; if(yych <= '/') goto yy2; if(yych >= ':') goto yy2; -yy67: ++YYCURSOR; +yy69: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; -yy68: if(yych <= '/') goto yy2; - if(yych <= '9') goto yy67; +yy70: if(yych <= '/') goto yy2; + if(yych <= '9') goto yy69; if(yych != ';') goto yy2; -yy69: yych = *++YYCURSOR; -yy70: -#line 262 +yy71: yych = *++YYCURSOR; +yy72: +#line 263 { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_BOOL(*rval, parse_iv(start + 2)); return 1; } -yy71: yych = *++YYCURSOR; -yy72: -#line 255 +yy73: yych = *++YYCURSOR; +yy74: +#line 256 { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_NULL(*rval); return 1; } -yy73: yych = *++YYCURSOR; +yy75: yych = *++YYCURSOR; if(yych <= ','){ if(yych != '+') goto yy2; } else { - if(yych <= '-') goto yy74; + if(yych <= '-') goto yy76; if(yych <= '/') goto yy2; - if(yych <= '9') goto yy75; + if(yych <= '9') goto yy77; goto yy2; } -yy74: yych = *++YYCURSOR; +yy76: yych = *++YYCURSOR; if(yych <= '/') goto yy2; if(yych >= ':') goto yy2; -yy75: ++YYCURSOR; +yy77: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; -yy76: if(yych <= '/') goto yy2; - if(yych <= '9') goto yy75; +yy78: if(yych <= '/') goto yy2; + if(yych <= '9') goto yy77; if(yych != ';') goto yy2; -yy77: yych = *++YYCURSOR; -yy78: -#line 236 +yy79: yych = *++YYCURSOR; +yy80: +#line 237 { int id; @@ -747,7 +763,7 @@ yy78: return 1; } } -#line 399 +#line 406 return 0; diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index f236f52984..1f11d3c3ca 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -233,6 +233,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) /*!re2c + "R:" iv ";" { int id; @@ -394,6 +395,12 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) return object_common2(UNSERIALIZE_PASSTHRU, elements); } +"}" { + /* this is the case where we have less data than planned */ + zend_error(E_NOTICE, "Unexpected end of serialized data"); + return 0; /* not sure if it should be 0 or 1 here? */ +} + any { return 0; } */