]> granicus.if.org Git - php/commitdiff
Fixed bug #38770 (unpack() broken with longs on 64 bit machines).
authorIlia Alshanetsky <iliaa@php.net>
Sun, 19 Nov 2006 18:20:48 +0000 (18:20 +0000)
committerIlia Alshanetsky <iliaa@php.net>
Sun, 19 Nov 2006 18:20:48 +0000 (18:20 +0000)
NEWS
ext/standard/pack.c
ext/standard/tests/strings/bug38770.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 9ba2a4faacfd29d3dd038e5f10d2ac846a50db49..19b88baf97ca71211bfecb19f92205ff55660714 100644 (file)
--- 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).
index 85b2acda744371b45257f492e42f0133d1cbdba2..6a5bad826a90c7dfd69757d2fb2ecfd89f834ddc 100644 (file)
@@ -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 (file)
index 0000000..2494a91
--- /dev/null
@@ -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