]> granicus.if.org Git - php/commitdiff
Fix signed integer overflow in SplObjectStorage unserialization
authorNikita Popov <nikita.ppv@gmail.com>
Mon, 23 Sep 2019 11:16:58 +0000 (13:16 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Mon, 23 Sep 2019 11:18:27 +0000 (13:18 +0200)
If count is ZEND_LONG_MIN the count-- loop underflows. This is
ultimately harmless, but results in a ubsan warning.

Fix this by adding a sanity check that the count isn't negative,
because that doesn't make sense...

ext/spl/spl_observer.c
ext/standard/tests/serialize/splobjectstorage_negative_count.phpt [new file with mode: 0644]

index adf59128a160b226c0532be69d75ea5f3f33bf92..605a9234d1f7c4b79d66f5a5ec522e2c7be8a17a 100644 (file)
@@ -787,6 +787,9 @@ SPL_METHOD(SplObjectStorage, unserialize)
 
        --p; /* for ';' */
        count = Z_LVAL_P(pcount);
+       if (count < 0) {
+               goto outexcept;
+       }
 
        ZVAL_UNDEF(&entry);
        ZVAL_UNDEF(&inf);
diff --git a/ext/standard/tests/serialize/splobjectstorage_negative_count.phpt b/ext/standard/tests/serialize/splobjectstorage_negative_count.phpt
new file mode 100644 (file)
index 0000000..4dda491
--- /dev/null
@@ -0,0 +1,15 @@
+--TEST--
+OSS-Fuzz: Unserializing SplObjectStorage with negative number of elements
+--FILE--
+<?php
+
+$str = 'C:16:"SplObjectStorage":25:{x:i:-9223372036854775808;}';
+try {
+    var_dump(unserialize($str));
+} catch (Exception $e) {
+    echo $e->getMessage(), "\n";
+}
+
+?>
+--EXPECT--
+Error at offset 24 of 25 bytes