PHP’s Integer Oddities

While working on an implementation of SMPP for PHP, I ran into some very odd behavior of integers.

SMPP has a number of commands, which are represented by unsigned long ints. If the high bit of the command is set, it indicates that the command is a response to a command. E.g. 0x00000002 is the SMPP bind_transmitter command, and 0x80000002 is bind_transmitter_resp, which is sent back in reply to a bind_transmitter request.

This causes some problems with PHP.

The crux of the problem seems to be the way PHP handles integers. It only supports signed ints, and they’re stored in a machine-dependent number of bytes. For a 32-bit system, it seems to use a signed long; for 64-bit, signed long long.

So, for example, if you run the following code on a 32-bit system, you won’t get the results you expect.

$before = 0x80000001; // Unsigned long, high bit is set
$bin = pack('N', $before); // Pack as an unsigned int
$after = unpack('N', $bin);
$after = $after[1];
echo "Before: $before\n";
echo " After: $after\n";

As you can see, unpack() doesn’t return the same value you pass to pack(), even though you ask it to be treated in the same way. According to the PHP developers, this is not a bug.

This behavior only occurs when dealing with ints which have the high bit set for the first byte of whatever platform you’re running on. So it works fine on a 64-bit system, but chokes on a 32-bit platform. I assume that if you substitute the value 0x8000000000000001, you’d get the same problem on a 64-bit platform.

I think this is dumb. PHP can obviously correctly represent 0x80000001, but it won’t after unpack() for some reason.

It gets worse…

Now consider this code:

$cmds = array(
    0x00000001 => 'bind_receiver',
    0x80000001 => 'bind_receiver_resp',
    0x00000002 => 'bind_transmitter',
    0x80000002 => 'bind_transmitter_resp'
);
echo 0x80000002 . "\n";
print_r($cmds);

This outputs:

2147483650
Array
(
    [1] => bind_receiver
    [-2147483648] => bind_transmitter_resp
    [2] => bind_transmitter
)

As you can see, array() screws up here. I’m not sure what it’s doing, but it seems to screw up any int with the high bit set, changing them all to 0xFFFFFFFF80000000. So you can’t use those values as array keys at all, since each successive int with the high bit set overwrites the previous. Again, this won’t be a problem on 64-bit systems, unless you’re using long longs.

Does anyone know if there’s a sane way of dealing with this in a machine-independent way?

2 Responses to “PHP’s Integer Oddities”

  1. klibza Says:

    Something todo with little an big endian…

  2. Mosaddek Says:

    Hi,
    can anyone help me about coding in PHP using SMPP to send sms from any Application PC/Server through SMSC server to mobile?
    I am trying to implement this from a SMSC server of an operator.
    Actually we can say that I am tring to develop an ESME tool that will be very much helpfull for the operator.There are also lots of codes in Java online. But I particularly want it to develop in PHP as I have developed another application for the system In PHP and I want to integrate with it.
    Thanks,
    Mosaddek

Leave a Reply