Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:26636 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 60640 invoked by uid 1010); 15 Nov 2006 22:50:39 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 60625 invoked from network); 15 Nov 2006 22:50:39 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 15 Nov 2006 22:50:39 -0000 X-Host-Fingerprint: 84.150.112.202 p549670CA.dip.t-dialin.net Received: from [84.150.112.202] ([84.150.112.202:6236] helo=localhost.localdomain) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 13/5E-53553-DB99B554 for ; Wed, 15 Nov 2006 17:50:37 -0500 To: internals@lists.php.net Date: Wed, 15 Nov 2006 23:50:34 +0100 User-Agent: Pan/0.14.2.91 (As She Crawled Across the Table (Debian GNU/Linux)) Message-ID: Reply-To: dsp@php.net MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-15 Content-Transfer-Encoding: 8bit X-Posted-By: 84.150.112.202 Subject: [PATCH] For Bug #38770 From: dsp@php.net (David Soria Parra) Hi internals, I tried to fix http://bugs.php.net/bug.php?id=38770. The pack and unpack function returns different values on different platform for options like "N". Example: print_r(unpack("N", pack("N", -3000))); prints -3000 und x86 and 4294937296 on x86_64. That happens because all the 32 bit integers are handled as long in the zend engine, but long differs from platform (8byte on x86_64 and 4byte on x86). If we pack e.g. a integer to big endian and unpack it to little endian, the long value will be filled by the complete 4byte integer value, so negative values are keeped. But on x86_64 (little endian) only the lower 4byte are set to the integer value while the highter 4bytes are set to zero. Thats why the long values that holds the negative integer value is treaten like a positive long. Thats why I added a few lines to the pack.c to detect if I get a negative integer (e.g. highest bit is set on little endian machines). For a negative integer I fill the higher 4bytes with 1, so that the long value is treaten as negative. You may ask why I take a 4byte _unsigned_ 32bit int from pack and test if the highest bit is set to "cast" it to an signed integer? Thats exactly what php does on x86 machines as it uses signed long internal. here is the patch (against 5.2.0 release): http://sqlbackup.net/data/pack.c.diff I tested it on x86_64 and x86 linux for various pack options. It#s not the best way, the best way might be to cast the signed integers to unsigned in the pack command not in the unpack, but that might be a BC. What do you think? Greets David