From: Nikita Popov Date: Mon, 16 Sep 2019 09:38:35 +0000 (+0200) Subject: Sanity-check array/object lengths during unserialization X-Git-Tag: php-7.4.0RC2~23 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4377a8ea41786d7b30e229378a3dc5b1b5b5289b;p=php Sanity-check array/object lengths during unserialization Avoid OOM conditions in unserialize due to overly large array or object length specifications. --- diff --git a/ext/standard/tests/serialize/bug74101.phpt b/ext/standard/tests/serialize/bug74101.phpt index 323f6c6f46..3eca747cb1 100644 --- a/ext/standard/tests/serialize/bug74101.phpt +++ b/ext/standard/tests/serialize/bug74101.phpt @@ -8,5 +8,5 @@ var_dump(unserialize($s)); --EXPECTF-- Warning: unserialize(): %s in %sbug74101.php on line %d -Notice: unserialize(): Error at offset 48 of 74 bytes in %sbug74101.php on line %d +Notice: unserialize(): Error at offset 46 of 74 bytes in %sbug74101.php on line %d bool(false) diff --git a/ext/standard/tests/serialize/unserialize_large.phpt b/ext/standard/tests/serialize/unserialize_large.phpt new file mode 100644 index 0000000000..9726306a8c --- /dev/null +++ b/ext/standard/tests/serialize/unserialize_large.phpt @@ -0,0 +1,25 @@ +--TEST-- +Unserializing payload with unrealistically large element counts +--FILE-- + +--EXPECTF-- +Notice: unserialize(): Error at offset 14 of 15 bytes in %s on line %d +bool(false) + +Notice: unserialize(): Error at offset 2 of 20 bytes in %s on line %d +bool(false) + +Notice: unserialize(): Error at offset 18 of 21 bytes in %s on line %d +bool(false) + +Warning: Insufficient data for unserializing - 1000000000 required, 1 present in %s on line %d + +Notice: unserialize(): Error at offset 20 of 21 bytes in %s on line %d +bool(false) diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index cef2eb0640..ba425e692e 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -953,7 +953,7 @@ use_double: *p = YYCURSOR; if (!var_hash) return 0; - if (elements < 0 || elements >= HT_MAX_SIZE) { + if (elements < 0 || elements >= HT_MAX_SIZE || elements > max - YYCURSOR) { return 0; } @@ -1124,10 +1124,11 @@ object ":" uiv ":" ["] { } elements = parse_iv2(*p + 2, p); - if (elements < 0) { + if (elements < 0 || elements > max - YYCURSOR) { zend_string_release_ex(class_name, 0); return 0; } + *p += 2; has_unserialize = !incomplete_class