Patch jsonrawserializable for JSON related Bug #75400
Patch version 2017-10-25 01:14 UTC
Return to Bug #75400 |
Download this patch
Patch Revisions:
Developer: jwalton@aretehs.com
diff -Naur php-7.1.10/ext/json/json.c php-new/ext/json/json.c
--- php-7.1.10/ext/json/json.c 2017-09-26 14:26:31.000000000 -0400
+++ php-new/ext/json/json.c 2017-10-24 21:09:54.401010732 -0400
@@ -40,6 +40,7 @@
static PHP_FUNCTION(json_last_error_msg);
PHP_JSON_API zend_class_entry *php_json_serializable_ce;
+PHP_JSON_API zend_class_entry *php_json_rawserializable_ce;
PHP_JSON_API ZEND_DECLARE_MODULE_GLOBALS(json)
@@ -85,6 +86,17 @@
};
/* }}} */
+/* {{{ JsonRawSerializable methods */
+ZEND_BEGIN_ARG_INFO(json_rawserialize_arginfo, 0)
+ /* No arguments */
+ZEND_END_ARG_INFO();
+
+static const zend_function_entry json_rawserializable_interface[] = {
+ PHP_ABSTRACT_ME(JsonRawSerializable, jsonSerialized, json_rawserialize_arginfo)
+ PHP_FE_END
+};
+/* }}} */
+
/* Register constant for options and errors */
#define PHP_JSON_REGISTER_CONSTANT(_name, _value) \
REGISTER_LONG_CONSTANT(_name, _value, CONST_CS | CONST_PERSISTENT);
@@ -93,9 +105,12 @@
static PHP_MINIT_FUNCTION(json)
{
zend_class_entry ce;
+ zend_class_entry cer;
INIT_CLASS_ENTRY(ce, "JsonSerializable", json_serializable_interface);
php_json_serializable_ce = zend_register_internal_interface(&ce);
+ INIT_CLASS_ENTRY(cer, "JsonRawSerializable", json_rawserializable_interface);
+ php_json_rawserializable_ce = zend_register_internal_interface(&cer);
/* options for json_encode */
PHP_JSON_REGISTER_CONSTANT("JSON_HEX_TAG", PHP_JSON_HEX_TAG);
diff -Naur php-7.1.10/ext/json/json_encoder.c php-new/ext/json/json_encoder.c
--- php-7.1.10/ext/json/json_encoder.c 2017-09-26 14:26:31.000000000 -0400
+++ php-new/ext/json/json_encoder.c 2017-10-24 21:03:04.069064504 -0400
@@ -535,6 +535,72 @@
}
/* }}} */
+static int php_json_encode_rawserializable_object(smart_str *buf, zval *val, int options, php_json_encoder *encoder) /* {{{ */
+{
+ zend_class_entry *ce = Z_OBJCE_P(val);
+ zval retval, fname;
+ HashTable* myht;
+ int return_code;
+
+ if (Z_TYPE_P(val) == IS_ARRAY) {
+ myht = Z_ARRVAL_P(val);
+ } else {
+ myht = Z_OBJPROP_P(val);
+ }
+
+ if (myht && ZEND_HASH_GET_APPLY_COUNT(myht) > 1) {
+ encoder->error_code = PHP_JSON_ERROR_RECURSION;
+ if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
+ smart_str_appendl(buf, "null", 4);
+ }
+ return FAILURE;
+ }
+
+
+ ZVAL_STRING(&fname, "jsonSerialized");
+
+ if (FAILURE == call_user_function_ex(EG(function_table), val, &fname, &retval, 0, NULL, 1, NULL) || Z_TYPE(retval) == IS_UNDEF) {
+ if (!EG(exception)) {
+ zend_throw_exception_ex(NULL, 0, "Failed calling %s::jsonSerialized()", ZSTR_VAL(ce->name));
+ }
+ zval_ptr_dtor(&fname);
+
+ if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
+ smart_str_appendl(buf, "null", 4);
+ }
+ return FAILURE;
+ }
+
+ if (EG(exception)) {
+ /* Error already raised */
+ zval_ptr_dtor(&retval);
+ zval_ptr_dtor(&fname);
+
+ if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
+ smart_str_appendl(buf, "null", 4);
+ }
+ return FAILURE;
+ }
+
+ 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 */
+ return_code = php_json_encode_array(buf, &retval, options, encoder);
+ } else if ((Z_TYPE(retval) == IS_STRING)) {
+ smart_str_appendl(buf, Z_STRVAL(retval), Z_STRLEN(retval));
+ return SUCCESS;
+ } else {
+ /* All other types, encode as normal */
+ return_code = php_json_encode_zval(buf, &retval, options, encoder);
+ }
+
+ zval_ptr_dtor(&retval);
+ zval_ptr_dtor(&fname);
+
+ return return_code;
+}
+/* }}} */
+
int php_json_encode_zval(smart_str *buf, zval *val, int options, php_json_encoder *encoder) /* {{{ */
{
again:
@@ -570,6 +636,8 @@
case IS_OBJECT:
if (instanceof_function(Z_OBJCE_P(val), php_json_serializable_ce)) {
return php_json_encode_serializable_object(buf, val, options, encoder);
+ }else if (instanceof_function(Z_OBJCE_P(val), php_json_rawserializable_ce)) {
+ return php_json_encode_rawserializable_object(buf, val, options, encoder);
}
/* fallthrough -- Non-serializable object */
case IS_ARRAY:
diff -Naur php-7.1.10/ext/json/php_json.h php-new/ext/json/php_json.h
--- php-7.1.10/ext/json/php_json.h 2017-09-26 14:26:31.000000000 -0400
+++ php-new/ext/json/php_json.h 2017-10-24 21:03:59.990147437 -0400
@@ -39,6 +39,7 @@
#endif
extern PHP_JSON_API zend_class_entry *php_json_serializable_ce;
+extern PHP_JSON_API zend_class_entry *php_json_rawserializable_ce;
/* error codes */
typedef enum {
|