I have a custom PHP extension which compares each byte in a binary data string. If both bytes at the same location in the file are on (or greater than 1) then the output of the same position will be on. Otherwise its off. The extension is as follows…
PHP_FUNCTION(compare_memory)
{
char *memory1, *memory2;
int memory1_length, memory2_length, return_length;
int length;
char *output;
int x;
zval *param;
// MAKE SURE WE HAVE
// string, (string_len,), string2, (string2_len) and length
if(ZEND_NUM_ARGS() != 2) WRONG_PARAM_COUNT;
// GET ARGUMENTS FROM PHP
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &memory1, &memory1_length, &memory2, &memory2_length) == FAILURE)
{
return;
}
if (memory1_length < memory2_length)
{
length = memory1_length;
return_length = memory2_length;
} else
{
length = memory2_length;
return_length = memory1_length;
}
if ((output = emalloc(return_length * sizeof(int))) == NULL)
{
printf("Error on malloc\n");
return;
}
// START COMPARING
for(x=1;x<length;x++)
{
if (memory1[x] > 0 && memory2[x] == 1)
{
output[x] = memory1[x];
}
}
RETVAL_STRINGL(output, return_length, 1);
efree(output);
}
I also have a PHP implementation as follows…
function compare_memory($data1, $data2)
{
$pack_one = pack("c", 1);
$pack_zero = pack("c", 0);
$strlen_data1 = strlen($data1);
$strlen_data2 = strlen($data2);
if ($strlen_data1 > $strlen_data2)
{
$strlen = $strlen_data1;
} else
{
$strlen = $strlen_data2;
}
$output = "";
for($x=0;$x<$strlen;$x++)
{
if ($strlen_data1 > $x)
{
$arr = unpack("cc", $data1[$x]);
$d1 = $arr["c"];
} else
{
$d1 = 0;
}
if ($strlen_data2 > $x)
{
$arr = unpack("cc", $data2[$x]);
$d2 = $arr["c"];
} else
{
$d2 = 0;
}
if ($d1 > 0 && $d2 == 1)
{
$output .= pack("c", $d1);
} else
{
$output .= $pack_zero;
}
}
return $output;
}
This extension was working fine with PHP 5.0 (which I’m aware is very old). We’ve recently upgraded to 5.3 and this no longer works. However the PHP implementation does.
I imagine there have been a whole host of changes to the PHP Internal API between the versions, including “Parameter parsing API unification will cause some functions to behave more or less strict when it comes to type juggling”.
Can you see anything obvious in the PHP Extension that may cause it to not work in more recent versions of PHP? My knowledge of C (and the PHP API) is sparse.
I’m not sure you can guarantee that
emallocis going to return you memory initialised with zeros. you might try using ecalloc instead.Or do it yourself:
Also, i don’t think
emallocever returnsNULL(Also i’m not sure why your
for(x=1;x<length;x++)starts from 1 instead of zero but perhaps there’s a reason)