I'm making slow progress on an updated version of AMFEXT. Most of the
encoding functionality is complete but I'm struggling a bit with the
decoding functions because I need to return zvals and other objects. In
particular, I'm getting some memory leak notifications and I'm also getting
some weird behavior when I add values to a HashTable and retrieve them
later. I'd very much appreciate some guidance. A code review would be
awesome if anyone is willing.
I've posted the extension's source on github at
https://github.com/sneakyimp/amfext
=== Problem 1: I pass a *zval to one of my functions by reference and it
gets pointed to a zval object representing a string. I was trying to check
Z_TYPE_P(myzval)==IS_STRING and even though it is a string with a type
value of 6, the check says otherwise, though. I'm baffled by this because
my code looks just like examples I've seen in 'Extending and Embedding
PHP.' Code:
zval *assoc_key;
MAKE_STD_ZVAL(assoc_key);
amf_read_string(buf, buf_len, buf_cursor, assoc_key, flags,
htComplexObjects, htObjectTypeTraits, htStrings TSRMLS_CC);
// had to remove this check because it was failing on empty strings
for some reason
if (Z_TYPE_P(assoc_key) == IS_STRING) {
// the baffling thing is it returns "String expected, but
returned object type is 6"
php_error_docref(NULL TSRMLS_CC, E_ERROR, "String expected, but
returned object type is %d", (unsigned int)Z_TYPE_P(assoc_key));
}
Here's a link to the source on github:
https://github.com/sneakyimp/amfext/blob/master/amf.c#L1242
=== Problem 2: Similar to the previous problem, but the issue is that
string zval is retrieved from a HashTable and when it comes out, the type
value is messed up value. Code:
// make sure it's a string
// WTF? Z_TYPE_P(strz) is never IS_STRING and Z_STRVAL_P returns
messed up values
// e.g., "ZVAL stored at index 0 is not a string, type=-30420640"
if (Z_TYPE_P(strz) != IS_STRING) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "ZVAL stored at index
%d is not a string, type=%d\n", (unsigned int)str_index, Z_STRVAL_P(strz));
}
Here's a link to the source on github:
https://github.com/sneakyimp/amfext/blob/master/amf.c#L1300
=== Problem 3: Memory leaks!
I concocted this test PHP script for my amf_decode function. It retrieves a
data file containing an amf3-serialized array:
array("abc", "abc", "abc", "a" => 1, "b" => 2, "c" => 3)
And then decodes it. The PHP script:
<?php
$dir = dirname(FILE);
$str = file_get_contents($dir . "/amf_arr_abc123.dat");
var_dump(amf_decode($str));
The output of the script:
array(6) {
["a"]=>
int(1)
["b"]=>
int(2)
["c"]=>
int(3)
[0]=>
string(3) "abc"
[1]=>
string(3) "abc"
[2]=>
string(3) "abc"
}
[Fri Oct 2 12:00:21 2015] Script:
'/home/jaith/src/php-5.5.29/ext/amf/jta/read_arr_test2.php'
/home/jaith/src/php-5.5.29/ext/amf/amf.c(1324) : Freeing 0x7F30D2091080
(32 bytes), script=/home/jaith/src/php-5.5.29/ext/amf/jta/read_arr_test2.php
Last leak repeated 3 times
[Fri Oct 2 12:00:21 2015] Script:
'/home/jaith/src/php-5.5.29/ext/amf/jta/read_arr_test2.php'
/home/jaith/src/php-5.5.29/ext/amf/amf.c(1330) : Freeing 0x7F30D2091270 (2
bytes), script=/home/jaith/src/php-5.5.29/ext/amf/jta/read_arr_test2.php
Last leak repeated 2 times
[Fri Oct 2 12:00:21 2015] Script:
'/home/jaith/src/php-5.5.29/ext/amf/jta/read_arr_test2.php'
/home/jaith/src/php-5.5.29/ext/amf/amf.c(1325) : Freeing 0x7F30D20914F0 (2
bytes), script=/home/jaith/src/php-5.5.29/ext/amf/jta/read_arr_test2.php
Last leak repeated 3 times
[Fri Oct 2 12:00:21 2015] Script:
'/home/jaith/src/php-5.5.29/ext/amf/jta/read_arr_test2.php'
/home/jaith/src/php-5.5.29/ext/amf/amf.c(1238) : Freeing 0x7F30D2092348
(32 bytes), script=/home/jaith/src/php-5.5.29/ext/amf/jta/read_arr_test2.php
[Fri Oct 2 12:00:21 2015] Script:
'/home/jaith/src/php-5.5.29/ext/amf/jta/read_arr_test2.php'
/home/jaith/src/php-5.5.29/ext/amf/amf.c(1333) : Freeing 0x7F30D2092AB8 (1
bytes), script=/home/jaith/src/php-5.5.29/ext/amf/jta/read_arr_test2.php
=== Total 13 memory leaks detected ===