diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2021-01-15 17:07:51 +0100 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2021-01-15 17:07:51 +0100 |
commit | 141c4be70a97ea9dd99b3a80543098c677d12c1e (patch) | |
tree | cfd79e53852dc4d1dbf9ec8bb58090911fd4e447 | |
parent | 21562aa98dd423a988770aee974377a77d980839 (diff) | |
download | php-git-141c4be70a97ea9dd99b3a80543098c677d12c1e.tar.gz |
Limit unserialization element count more aggressively
This is slightly more aggressive about rejecting obviously incorrect
element counts. Previously the number of elements was allowed to
match the number of characters. Now it is the number of characters
divided by two (this can actually be increased further to at least 4).
This doesn't really matter in the grand scheme of things (as it
just cuts maximum memory usage by half), but should fix
oss-fuzz #29356.
-rw-r--r-- | ext/standard/var_unserializer.re | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index c5a1476938..3c620613ee 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -29,6 +29,10 @@ #define VAR_WAKEUP_FLAG 1 #define VAR_UNSERIALIZE_FLAG 2 +/* Each element is encoded using at least 2 characters. */ +#define IS_FAKE_ELEM_COUNT(num_elems, serialized_len) \ + ((num_elems) > (serialized_len) / 2) + typedef struct { zend_long used_slots; void *next; @@ -1001,7 +1005,7 @@ use_double: *p = YYCURSOR; if (!var_hash) return 0; - if (elements < 0 || elements >= HT_MAX_SIZE || elements > max - YYCURSOR) { + if (elements < 0 || elements >= HT_MAX_SIZE || IS_FAKE_ELEM_COUNT(elements, max - YYCURSOR)) { return 0; } @@ -1169,7 +1173,7 @@ object ":" uiv ":" ["] { } elements = parse_iv2(*p + 2, p); - if (elements < 0 || elements > max - YYCURSOR) { + if (elements < 0 || IS_FAKE_ELEM_COUNT(elements, max - YYCURSOR)) { zend_string_release_ex(class_name, 0); return 0; } |