REGISTER_LONG_CONSTANT("JSON_HEX_QUOT", PHP_JSON_HEX_QUOT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("JSON_FORCE_OBJECT", PHP_JSON_FORCE_OBJECT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("JSON_NUMERIC_CHECK", PHP_JSON_NUMERIC_CHECK, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("JSON_UNESCAPED_SLASHES", PHP_JSON_UNESCAPED_SLASHES, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("JSON_PRETTY_PRINT", PHP_JSON_PRETTY_PRINT, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("JSON_UNESCAPED_UNICODE", PHP_JSON_UNESCAPED_UNICODE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("JSON_PARTIAL_OUTPUT_ON_ERROR", PHP_JSON_PARTIAL_OUTPUT_ON_ERROR, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("JSON_ERROR_NONE", PHP_JSON_ERROR_NONE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("JSON_ERROR_DEPTH", PHP_JSON_ERROR_DEPTH, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("JSON_ERROR_CTRL_CHAR", PHP_JSON_ERROR_CTRL_CHAR, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("JSON_ERROR_SYNTAX", PHP_JSON_ERROR_SYNTAX, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("JSON_ERROR_UTF8", PHP_JSON_ERROR_UTF8, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("JSON_ERROR_RECURSION", PHP_JSON_ERROR_RECURSION, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("JSON_ERROR_INF_OR_NAN", PHP_JSON_ERROR_INF_OR_NAN, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("JSON_ERROR_UNSUPPORTED_TYPE", PHP_JSON_ERROR_UNSUPPORTED_TYPE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("JSON_OBJECT_AS_ARRAY", PHP_JSON_OBJECT_AS_ARRAY, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("JSON_BIGINT_AS_STRING", PHP_JSON_BIGINT_AS_STRING, CONST_CS | CONST_PERSISTENT);
+
return SUCCESS;
}
/* }}} */
if (utf16) {
efree(utf16);
}
- if (len < 0) {
+ if (ulen < 0) {
JSON_G(error_code) = PHP_JSON_ERROR_UTF8;
- if (!PG(display_errors)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid UTF-8 sequence in argument");
- }
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid UTF-8 sequence in argument");
smart_str_appendl(buf, "null", 4);
} else {
smart_str_appendl(buf, "\"\"", 2);
}
smart_str_appendc(buf, '"');
- efree(utf16);
+ if (utf16) {
+ efree(utf16);
+ }
+}
+/* }}} */
+
+
+static void json_encode_serializable_object(smart_str *buf, zval *val, int options TSRMLS_DC) /* {{{ */
+{
+ zend_class_entry *ce = Z_OBJCE_P(val);
+ zval *retval = NULL, fname;
+ HashTable* myht;
+
+ if (Z_TYPE_P(val) == IS_ARRAY) {
+ myht = HASH_OF(val);
+ } else {
+ myht = Z_OBJPROP_P(val);
+ }
+
+ if (myht && myht->nApplyCount > 1) {
++ JSON_G(error_code) = PHP_JSON_ERROR_RECURSION;
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected");
+ smart_str_appendl(buf, "null", 4);
+ return;
+ }
+
+ ZVAL_STRING(&fname, "jsonSerialize", 0);
+
+ if (FAILURE == call_user_function_ex(EG(function_table), &val, &fname, &retval, 0, NULL, 1, NULL TSRMLS_CC) || !retval) {
+ zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Failed calling %s::jsonSerialize()", ce->name);
+ smart_str_appendl(buf, "null", sizeof("null") - 1);
+ return;
+ }
+
+ if (EG(exception)) {
+ /* Error already raised */
+ zval_ptr_dtor(&retval);
+ smart_str_appendl(buf, "null", sizeof("null") - 1);
+ return;
+ }
+
+ if ((Z_TYPE_P(retval) == IS_OBJECT) &&
+ (Z_OBJ_HANDLE_P(retval) == Z_OBJ_HANDLE_P(val))) {
+ /* Handle the case where jsonSerialize does: return $this; by going straight to encode array */
+ json_encode_array(buf, &retval, options TSRMLS_CC);
+ } else {
+ /* All other types, encode as normal */
+ php_json_encode(buf, retval, options TSRMLS_CC);
+ }
+
+ zval_ptr_dtor(&retval);
}
/* }}} */
#define PHP_JSON_HEX_QUOT (1<<3)
#define PHP_JSON_FORCE_OBJECT (1<<4)
#define PHP_JSON_NUMERIC_CHECK (1<<5)
-#define PHP_JSON_PARTIAL_OUTPUT_ON_ERROR (1<<9)
+#define PHP_JSON_UNESCAPED_SLASHES (1<<6)
+#define PHP_JSON_PRETTY_PRINT (1<<7)
+#define PHP_JSON_UNESCAPED_UNICODE (1<<8)
++#define PHP_JSON_PARTIAL_OUTPUT_ON_ERROR (1<<9)
+
+/* Internal flags */
+#define PHP_JSON_OUTPUT_ARRAY 0
+#define PHP_JSON_OUTPUT_OBJECT 1
+
+/* json_decode() options */
+#define PHP_JSON_OBJECT_AS_ARRAY (1<<0)
+#define PHP_JSON_BIGINT_AS_STRING (1<<1)
+
+static inline void php_json_decode(zval *return_value, char *str, int str_len, zend_bool assoc, long depth TSRMLS_DC)
+{
+ php_json_decode_ex(return_value, str, str_len, assoc ? PHP_JSON_OBJECT_AS_ARRAY : 0, depth TSRMLS_CC);
+}
-#define PHP_JSON_OUTPUT_ARRAY 0
-#define PHP_JSON_OUTPUT_OBJECT 1
#endif /* PHP_JSON_H */
--- /dev/null
- var_dump(json_encode("ab\xE0c"));
- var_dump(json_encode(array("ab\xE0", "ab\xE0c", "abc")));
+--TEST--
+Bug #43941 (json_encode() invalid UTF-8)
+--SKIPIF--
+<?php if (!extension_loaded("json")) print "skip"; ?>
+--FILE--
+<?php
+
+var_dump(json_encode("abc"));
+var_dump(json_encode("ab\xE0"));
- string(4) "null"
++var_dump(json_encode("ab\xE0", JSON_PARTIAL_OUTPUT_ON_ERROR));
++var_dump(json_encode(array("ab\xE0", "ab\xE0c", "abc"), JSON_PARTIAL_OUTPUT_ON_ERROR));
+
+echo "Done\n";
+?>
+--EXPECTF--
+string(5) ""abc""
++
++Warning: json_encode(): Invalid UTF-8 sequence in argument in %s on line %d
++bool(false)
++
++Warning: json_encode(): Invalid UTF-8 sequence in argument in %s on line %d
+string(4) "null"
-
++
++Warning: json_encode(): Invalid UTF-8 sequence in argument in %s on line %d
++
++Warning: json_encode(): Invalid UTF-8 sequence in argument in %s on line %d
+string(17) "[null,null,"abc"]"
+Done
--- /dev/null
- var_dump(json_encode($obj1));
+--TEST--
+Bug #61978 (Object recursion not detected for classes that implement JsonSerializable)
+--SKIPIF--
+<?php if (!extension_loaded("json")) print "skip"; ?>
+--FILE--
+<?php
+
+class JsonTest1 {
+ public $test;
+ public $me;
+ public function __construct() {
+ $this->test = '123';
+ $this->me = $this;
+ }
+}
+
+class JsonTest2 implements JsonSerializable {
+ public $test;
+ public function __construct() {
+ $this->test = '123';
+ }
+ public function jsonSerialize() {
+ return array(
+ 'test' => $this->test,
+ 'me' => $this
+ );
+ }
+}
+
+
+$obj1 = new JsonTest1();
- var_dump(json_encode($obj2));
++var_dump(json_encode($obj1, JSON_PARTIAL_OUTPUT_ON_ERROR));
+
+echo "\n==\n";
+
+$obj2 = new JsonTest2();
++var_dump(json_encode($obj2, JSON_PARTIAL_OUTPUT_ON_ERROR));
+
+?>
+--EXPECTF--
+Warning: json_encode(): recursion detected in %s on line %d
+string(44) "{"test":"123","me":{"test":"123","me":null}}"
+
+==
+
+Warning: json_encode(): recursion detected in %s on line %d
+string(44) "{"test":"123","me":{"test":"123","me":null}}"