summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIlia Alshanetsky <iliaa@php.net>2006-11-19 18:20:48 +0000
committerIlia Alshanetsky <iliaa@php.net>2006-11-19 18:20:48 +0000
commit0d338f463cc7f7980a1ac58809c14c005dd3e9ac (patch)
treeceed0ccf975a7ee0ebdc11198d0e7e1073bd78de
parentc06f9e1efe5375abcbb507876e04e893885e4ade (diff)
downloadphp-git-0d338f463cc7f7980a1ac58809c14c005dd3e9ac.tar.gz
Fixed bug #38770 (unpack() broken with longs on 64 bit machines).
-rw-r--r--NEWS2
-rw-r--r--ext/standard/pack.c16
-rw-r--r--ext/standard/tests/strings/bug38770.phpt25
3 files changed, 38 insertions, 5 deletions
diff --git a/NEWS b/NEWS
index 9ba2a4faac..19b88baf97 100644
--- a/NEWS
+++ b/NEWS
@@ -74,6 +74,8 @@ PHP NEWS
(Dmitry)
- Fixed bug #39090 (DirectoryFilterDots doxygen docs and example is wrong).
(Marcus)
+- Fixed bug #38770 (unpack() broken with longs on 64 bit machines). (Ilia,
+ David Soria Parra).
- Fixed bug #38698 (for some keys cdbmake creates corrupted db and cdb can't
read valid db). (Marcus)
- Fixed bug #38680 (Added missing handling of basic types in json_decode).
diff --git a/ext/standard/pack.c b/ext/standard/pack.c
index 85b2acda74..6a5bad826a 100644
--- a/ext/standard/pack.c
+++ b/ext/standard/pack.c
@@ -753,14 +753,16 @@ PHP_FUNCTION(unpack)
case 'i':
case 'I': {
- long v;
+ long v = 0;
int issigned = 0;
if (type == 'i') {
issigned = input[inputpos + (machine_little_endian ? (sizeof(int) - 1) : 0)] & 0x80;
- }
+ } else if (sizeof(long) > 4 && (input[inputpos + machine_endian_long_map[3]] & 0x80) == 0x80) {
+ v = ~INT_MAX;
+ }
- v = php_unpack(&input[inputpos], sizeof(int), issigned, int_map);
+ v |= php_unpack(&input[inputpos], sizeof(int), issigned, int_map);
add_assoc_long(return_value, n, v);
break;
}
@@ -771,7 +773,7 @@ PHP_FUNCTION(unpack)
case 'V': {
int issigned = 0;
int *map = machine_endian_long_map;
- long v;
+ long v = 0;
if (type == 'l') {
issigned = input[inputpos + (machine_little_endian ? 3 : 0)] & 0x80;
@@ -781,7 +783,11 @@ PHP_FUNCTION(unpack)
map = little_endian_long_map;
}
- v = php_unpack(&input[inputpos], 4, issigned, map);
+ if (sizeof(long) > 4 && (input[inputpos + machine_endian_long_map[3]] & 0x80) == 0x80) {
+ v = ~INT_MAX;
+ }
+
+ v |= php_unpack(&input[inputpos], 4, issigned, map);
add_assoc_long(return_value, n, v);
break;
}
diff --git a/ext/standard/tests/strings/bug38770.phpt b/ext/standard/tests/strings/bug38770.phpt
new file mode 100644
index 0000000000..2494a911bd
--- /dev/null
+++ b/ext/standard/tests/strings/bug38770.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Bug #38770 (unpack() broken with longs on 64 bit machines)
+--FILE--
+<?php
+
+foreach (array('N','I','l') as $v) {
+ print_r(unpack($v, pack($v, -30000)));
+}
+
+echo "Done\n";
+?>
+--EXPECT--
+Array
+(
+ [1] => -30000
+)
+Array
+(
+ [1] => -30000
+)
+Array
+(
+ [1] => -30000
+)
+Done