I finally found an almost satisfying answer from this blog of a security expert (Gynvael) and by reading source code. From the former, I'm only quoting the parts that answer my initial question: why (loose, ==) comparing a string/number/resource to an object/array seems to always return false? The algorithm in charge of equivalent comparison (==
) can be found here.
The main mechanics of the equality operator are implemented in the compare_function in php-src/Zend/zend_operators.c, however many cases call other functions or use big macros (which then call other functions that use even more macros), so reading this isn't too pleasant.
The operator basically works in two steps:
If both operands are of a type that the compare_function knows how to compare they are compared. This behavior includes the following pairs of types (please note the equality operator is symmetrical so comparison of A vs B is the same as B vs A):
• LONG vs LONG
• LONG vs DOUBLE (+ symmetrical)
• DOUBLE vs DOUBLE
• ARRAY vs ARRAY
• NULL vs NULL
• NULL vs BOOL (+ symmetrical)
• NULL vs OBJECT (+ symmetrical)
• BOOL vs BOOL
• STRING vs STRING
• and OBJECT vs OBJECT
In case the pair of types is not on the above list the compare_function tries to cast the operands to either the type of the second operand (in case of OBJECTs with cast_object handler), cast to BOOL (in case the second type is either NULL or BOOL), or cast to either LONG or DOUBLE in most other cases. After the cast the compare_function is rerun.
I think that all other cases return false.