$ This clone coding in JsonSerializable

In this simplified case, PHP segfault occurs (output 127):

class Datum implements \JsonSerializable{
  public function jsonSerialize(){
    return clone $this;
  }
}
echo json_encode(new Datum);

The last line of code leads to the conclusion (127). I cannot get any stack in the current environment.

Meanwhile, the token is being deleted clone.

Is there any possible explanation why this is happening?

+4
source share
1 answer

This code leads to infinite recursion.

It looks like the PHP JSON module supports JsonSerializablethis way (pseudocode):

function json_encode($data){
    if($data instanceof JsonSerializable) return json_encode($data->jsonSerialize());
    else real_json_encode($data); // handling primitive data or arrays or pure data objects
}

If you return another instance of JsonSerializable, json_encode will attempt to serialize it again, resulting in infinite recursion.

return $this;, , , - json_encode, json_encode, , $this. , $a !== clone $a.

php-src.

// in php_json_encode_zval
if (instanceof_function(Z_OBJCE_P(val), php_json_serializable_ce)) {
    return php_json_encode_serializable_object(buf, val, options, encoder);
}

// in php_json_encode_serializable_object
if ((Z_TYPE(retval) == IS_OBJECT) &&
    (Z_OBJ(retval) == Z_OBJ_P(val))) {
    /* Handle the case where jsonSerialize does: return $this; by going straight to encode array */
    PHP_JSON_HASH_APPLY_PROTECTION_DEC(myht);
    return_code = php_json_encode_array(buf, &retval, options, encoder);
} else {
    /* All other types, encode as normal */
    return_code = php_json_encode_zval(buf, &retval, options, encoder);
    PHP_JSON_HASH_APPLY_PROTECTION_DEC(myht);
}

, PHP return $this; ( , ), - , Z_OBJ(retval) == Z_OBJ_P(val) false, else, php_json_encode_zval .

TL; DR, : return (array) $this; clone $this;.

+1

Source: https://habr.com/ru/post/1662300/


All Articles