Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the number 16 converted to float(6.1026988574311E_320) by PHP using Zend_Amf

The Zend_Amf specification states that a Number type returned from flash will map to a float in PHP. Fine. But why does the number 16 get returned as 6.1026988574311E_320 ? PHP version is 5.2.9 running on OS X.

I have tried forcing a cast to integer in PHP (the above value gets rounded to 0) and also from Actionscript using int(16) - the latter comes through as NULL. How can ensure that Flash returns an integer via AMF and that PHP can deal with it?

like image 340
codecowboy Avatar asked Dec 01 '25 19:12

codecowboy


2 Answers

You have a classic endian problem. Looks like either Zend or flash is doing the wrong thing with the endianness of this double. Here is the a program that prints the double (and its hex value). It then reverses the endianness and prints it again.

#include <stdio.h>
#include <stdint.h>

int main(void)
{
  double d = 16;
  uint32_t *i = (uint32_t *)(&d);
  uint8_t *c = (uint8_t *)(&d);
  size_t j;

  printf("%08x %08x %lg\n", i[1], i[0], d);

  for(j = 0; j < sizeof(double) / 2; j++)
  {
        uint8_t tmp;

        tmp = c[j];
        c[j] = c[sizeof(double) - j - 1];
        c[sizeof(double) - j - 1] = tmp;
    }

  printf("%08x %08x %lg\n", i[1], i[0], d);

  return 0;
}

On an Intel (little endian processor), you get this output

40300000 00000000 16
00000000 00003040 6.1027e-320

Are you perhaps running this on a PPC Mac (big endian)? Seems like one of your tools is not doing the right thing on your architecture. File a bug with the vendors.

As a hacky workaround, I suggest turning your number into a string and then converting it back to a double on the other end.

like image 135
Variable Length Coder Avatar answered Dec 04 '25 07:12

Variable Length Coder


I don't know entirely what is going wrong in your situation, but I think I may be able to partially illuminate what is happening to your code. I ran the following quick hack to test a theory:

void hexdump_double(double dbl)
{
    assert(8 == sizeof(dbl));
    printf("double: %02X %02X %02X %02X %02X %02X %02X %02X (%lg)\n",  
           ((char *)&(dbl))[0],
           ((char *)&(dbl))[1],
           ((char *)&(dbl))[2],
           ((char *)&(dbl))[3],
           ((char *)&(dbl))[4],
           ((char *)&(dbl))[5],
           ((char *)&(dbl))[6],
           ((char *)&(dbl))[7],
           dbl);
}

int main()
{
    hexdump_double(6.1026988574311E-320);
}

Which produces some exciting output:

double: 40 30 00 00 00 00 00 00 (6.1027e-320)

As you can see, that little floating-point number isn't any random pattern of bits. However, it also doesn't look to be related to "16."

Where Zend_Amf documentation states that ActionScript Number type is returned as a PHP float, what is meant is the class Number documented by Adobe: Adobe.com Flex documentation. It does not mean that any "number" will be passed as a double.

An int with value less than 2^29 will be returned transmitted in AMF as an integer type, and I assume Zend_Amf will return this as an integer.

How are you transmitting the AMF object from your ActionScript? Is it feasible to dump the bytes being sent?

like image 34
Heath Hunnicutt Avatar answered Dec 04 '25 08:12

Heath Hunnicutt



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!