Internal Type Juggling in PHP 5.2 vs PHP 5.3 September 20, 2011

There is an undocumented case where the output of an internal function is different in PHP 5.2 vs PHP 5.3 when you pass it an invalid argument.

For example, strlen returns different values and warnings/notices when attempting to pass it an array.

PHP 5.2

> var_dump(strlen(array()));
PHP Notice:  Array to string conversion in php  shell code on line 1

Notice: Array to string conversion in php  shell code on line 1
int(5)

PHP 5.3

> var_dump(strlen(array()));
PHP Warning:  strlen() expects parameter 1 to be string, array given in php  shell code on line 1
PHP Stack trace:
PHP   1. {main}() php shell code:0
PHP   2. strlen() php shell code:1

Warning: strlen() expects parameter 1 to be string, array given in php  shell code on line 1

Call Stack:
  467.9296     320928   1. {main}() php  shell code:0
  467.9296     321072   2. strlen() php  shell code:1

NULL

The E_WARNING and return value of NULL in PHP 5.3 is preferred, but I still wanted to know why PHP 5.2 was returning int(5). I tracked down the reason to this subversion commit and this patch.

In the above patch, I see that strlen and other functions(method_exists, property_exists, function_exists, strcmp, strncmp, strcasecmp, strncasecmp, defined, is_a_impl) were not using zend_parse_parameters to get the arguments. This was preventing the standard validations and warnings from running for that function. Also, those functions were incorrectly casting the arguments to string with convert_to_string_ex. That is why, in PHP 5.2, strlen() of array() is int(5); because, casting array() to string returns "Array".

Now, in PHP 5.3, those functions will no longer coerce the arguments to strings, will return NULL, and will issue a warning when invalid arguments have been provided. Thanks stas.

 

comments powered by Disqus