php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Return to Bug #75400
Patch jsonrawserializable revision 2017-10-25 01:14 UTC by jwalton at aretehs dot com

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 {
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Thu Jun 27 02:01:25 2019 UTC