]> granicus.if.org Git - php/commitdiff
Add optional second arg to unserialize()
authorSara Golemon <pollita@php.net>
Thu, 16 May 2013 21:37:36 +0000 (14:37 -0700)
committerSara Golemon <pollita@php.net>
Thu, 16 May 2013 22:18:35 +0000 (15:18 -0700)
Returns the number of bytes consumed by reference for
streaming unserialization.

Actual unserialization behavior is not modified at all.

The need for this came up while trying to parse SplDoublyLinkedList's
serialization format which uses a non-standard stream of serialized values.

ext/standard/basic_functions.c
ext/standard/tests/serialize/serialization_error_001.phpt
ext/standard/tests/serialize/unserialize_consumed.phpt [new file with mode: 0644]
ext/standard/var.c

index 9c91404eff05fe94df535766df71da06be2dab3a..13791177457e857831ef86ae90b20b23974e3a0b 100644 (file)
@@ -2679,6 +2679,7 @@ ZEND_END_ARG_INFO()
 
 ZEND_BEGIN_ARG_INFO(arginfo_unserialize, 0)
        ZEND_ARG_INFO(0, variable_representation)
+       ZEND_ARG_INFO(1, consumed)
 ZEND_END_ARG_INFO()
 
 ZEND_BEGIN_ARG_INFO_EX(arginfo_memory_get_usage, 0, 0, 0)
index da6f50cc02b29c00161cb547c66cbe8db08fd61b..c6c17512f39785b6ea1ff1e84770ecaef2487de6 100644 (file)
@@ -21,7 +21,7 @@ var_dump( unserialize() );
 
 //Test serialize with one more than the expected number of arguments
 var_dump( serialize(1,2) );
-var_dump( unserialize(1,2) );
+var_dump( unserialize(1,$x,2) );
 
 echo "Done";
 ?>
@@ -31,12 +31,12 @@ echo "Done";
 Warning: serialize() expects exactly 1 parameter, 0 given in %s on line 16
 NULL
 
-Warning: unserialize() expects exactly 1 parameter, 0 given in %s on line 17
+Warning: unserialize() expects at least 1 parameter, 0 given in %s on line 17
 bool(false)
 
 Warning: serialize() expects exactly 1 parameter, 2 given in %s on line 20
 NULL
 
-Warning: unserialize() expects exactly 1 parameter, 2 given in %s on line 21
+Warning: unserialize() expects at most 2 parameters, 3 given in %s on line 21
 bool(false)
 Done
diff --git a/ext/standard/tests/serialize/unserialize_consumed.phpt b/ext/standard/tests/serialize/unserialize_consumed.phpt
new file mode 100644 (file)
index 0000000..6cc11e2
--- /dev/null
@@ -0,0 +1,27 @@
+--TEST--
+Unserialization of partial strings
+--FILE--
+<?php
+$data = [123,4.56,true];
+$ser = serialize($data);
+$serlen = strlen($ser);
+
+$unser = unserialize($ser, $consumed);
+echo "Consume full string: ";
+var_dump($serlen == $consumed);
+echo "Return original data: ";
+var_dump($unser === $data);
+
+$ser .= "junk\x01data";
+$unser = unserialize($ser, $consumed);
+echo "Consume full string(junk): ";
+var_dump($serlen == $consumed);
+echo "Return original data(junk): ";
+var_dump($unser === $data);
+
+--EXPECT--
+Consume full string: bool(true)
+Return original data: bool(true)
+Consume full string(junk): bool(true)
+Return original data(junk): bool(true)
+
index f76a14cfa66410880fd2208f50d766a3de7ddfbe..4acc6f57b7b71ca29a81ed4163c65b39ea9de27e 100644 (file)
@@ -945,7 +945,7 @@ PHP_FUNCTION(serialize)
 }
 /* }}} */
 
-/* {{{ proto mixed unserialize(string variable_representation)
+/* {{{ proto mixed unserialize(string variable_representation[, int &consumed])
    Takes a string representation of variable and recreates it */
 PHP_FUNCTION(unserialize)
 {
@@ -953,8 +953,9 @@ PHP_FUNCTION(unserialize)
        int buf_len;
        const unsigned char *p;
        php_unserialize_data_t var_hash;
+       zval *consumed = NULL;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &buf, &buf_len, &consumed) == FAILURE) {
                RETURN_FALSE;
        }
 
@@ -973,6 +974,11 @@ PHP_FUNCTION(unserialize)
                RETURN_FALSE;
        }
        PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+
+       if (consumed) {
+               zval_dtor(consumed);
+               ZVAL_LONG(consumed, ((char*)p) - buf);
+       }
 }
 /* }}} */