summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS1
-rw-r--r--UPGRADING3
-rw-r--r--ext/standard/pack.c13
-rw-r--r--ext/standard/tests/strings/unpack_error.phpt6
-rw-r--r--ext/standard/tests/strings/unpack_offset.phpt17
5 files changed, 35 insertions, 5 deletions
diff --git a/NEWS b/NEWS
index b0ee6b88e5..0aff059ebc 100644
--- a/NEWS
+++ b/NEWS
@@ -53,5 +53,6 @@ PHP NEWS
(Ilia) (Julien)
. Implemented FR #69359 (Provide a way to fetch the current environment
variables). (Ferenc)
+ . unpack() function accepts an additional optional argument $offset. (Dmitry)
<<< NOTE: Insert NEWS from last stable release here prior to actual release! >>>
diff --git a/UPGRADING b/UPGRADING
index 7865df65e5..94cea6f9a2 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -63,6 +63,9 @@ PHP 7.1 UPGRADE NOTES
pg_fetch_row().
- pg_select() accepts 4th optional result type parameter like pg_fetch_row().
- parse_url() is more restrictive now and supports RFC3986.
+- unpack() accepts an additional optional $offset argument. '@' format code
+ (that specifes an absolute position) is applyed to input data after
+ the $offset argument.
========================================
6. New Functions
diff --git a/ext/standard/pack.c b/ext/standard/pack.c
index a24ee69ad2..1d353d1743 100644
--- a/ext/standard/pack.c
+++ b/ext/standard/pack.c
@@ -551,9 +551,10 @@ PHP_FUNCTION(unpack)
zend_string *formatarg, *inputarg;
zend_long formatlen, inputpos, inputlen;
int i;
+ zend_long offset = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &formatarg,
- &inputarg) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|l", &formatarg,
+ &inputarg, &offset) == FAILURE) {
return;
}
@@ -563,6 +564,14 @@ PHP_FUNCTION(unpack)
inputlen = ZSTR_LEN(inputarg);
inputpos = 0;
+
+ if (offset < 0 || offset > inputlen) {
+ php_error_docref(NULL, E_WARNING, "Offset " ZEND_LONG_FMT " is out of input range" , offset);
+ RETURN_FALSE;
+ }
+ input += offset;
+ inputlen -= offset;
+
array_init(return_value);
while (formatlen-- > 0) {
diff --git a/ext/standard/tests/strings/unpack_error.phpt b/ext/standard/tests/strings/unpack_error.phpt
index 1ef97ccbaf..3a4f334c3b 100644
--- a/ext/standard/tests/strings/unpack_error.phpt
+++ b/ext/standard/tests/strings/unpack_error.phpt
@@ -15,7 +15,7 @@ var_dump( unpack() );
echo "\n-- Testing unpack() function with more than expected no. of arguments --\n";
$extra_arg = 10;
-var_dump(unpack("I", pack("I", 65534), $extra_arg));
+var_dump(unpack("I", pack("I", 65534), 0, $extra_arg));
echo "\n-- Testing unpack() function with invalid format character --\n";
$extra_arg = 10;
@@ -27,12 +27,12 @@ var_dump(unpack("G", pack("I", 65534)));
-- Testing unpack() function with no arguments --
-Warning: unpack() expects exactly 2 parameters, 0 given in %s on line %d
+Warning: unpack() expects at least 2 parameters, 0 given in %s on line %d
NULL
-- Testing unpack() function with more than expected no. of arguments --
-Warning: unpack() expects exactly 2 parameters, 3 given in %s on line %d
+Warning: unpack() expects at most 3 parameters, 4 given in %s on line %d
NULL
-- Testing unpack() function with invalid format character --
diff --git a/ext/standard/tests/strings/unpack_offset.phpt b/ext/standard/tests/strings/unpack_offset.phpt
new file mode 100644
index 0000000000..c8c08e74f2
--- /dev/null
+++ b/ext/standard/tests/strings/unpack_offset.phpt
@@ -0,0 +1,17 @@
+--TEST--
+unpack() with offset
+--FILE--
+<?php
+$data = "pad" . pack("ll", 0x01020304, 0x05060708);
+
+$a = unpack("l2", $data, 3);
+printf("0x%08x 0x%08x\n", $a[1], $a[2]);
+
+printf("0x%08x 0x%08x\n",
+ unpack("l", $data, 3)[1],
+ unpack("@4/l", $data, 3)[1]);
+?>
+--EXPECT--
+0x01020304 0x05060708
+0x01020304 0x05060708
+