php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login

Patch json-decode-warnings for JSON related Bug #52829

Patch version 2010-09-14 05:48 UTC

Return to Bug #52829 | Download this patch
Patch Revisions:

Developer: aharvey@php.net

diff --git a/ext/json/JSON_parser.c b/ext/json/JSON_parser.c
index ef05f3b..a7f0162 100644
--- a/ext/json/JSON_parser.c
+++ b/ext/json/JSON_parser.c
@@ -389,6 +389,31 @@ static void utf16_to_utf8(smart_str *buf, unsigned short utf16)
     }
 }
 
+/* Wrapper functions to emit a warning if a JSON object has duplicate names,
+ * which are technically valid under the RFC, but not something we can handle
+ * safely. */
+static void add_assoc_zval_warn(zval *arg, const char *key, uint key_len, zval *value TSRMLS_DC) {
+	ulong h = zend_get_hash_value(key, key_len);
+
+	if (zend_hash_quick_exists(Z_ARRVAL_P(arg), key, key_len, h)) {
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Duplicate name '%s' within JSON object; only the last value will be used", key);
+	}
+
+	add_assoc_zval_ex(arg, key, key_len, value TSRMLS_CC);
+}
+
+static void add_property_zval_warn(zval *arg, const char *key, uint key_len, zval *value TSRMLS_DC) {
+	ulong h = zend_get_hash_value(key, key_len);
+	HashTable *properties = Z_OBJ_HANDLER_P(arg, get_properties)(arg);
+
+	if (properties && zend_hash_quick_exists(properties, key, key_len, h)) {
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Duplicate name '%s' within JSON object; only the last value will be used", key);
+	}
+
+	add_property_zval_ex(arg, key, key_len, value TSRMLS_CC);
+}
+
+
 static void attach_zval(JSON_parser jp, int up, int cur, smart_str *key, int assoc TSRMLS_DC)
 {
     zval *root = jp->the_zstack[up];
@@ -403,12 +428,12 @@ static void attach_zval(JSON_parser jp, int up, int cur, smart_str *key, int ass
     {
         if (!assoc)
         {
-            add_property_zval_ex(root, (key->len ? key->c : "_empty_"), (key->len ? (key->len + 1) : sizeof("_empty_")), child TSRMLS_CC);
+            add_property_zval_warn(root, (key->len ? key->c : "_empty_"), (key->len ? (key->len + 1) : sizeof("_empty_")), child TSRMLS_CC);
             Z_DELREF_P(child);
         }
         else
         {
-            add_assoc_zval_ex(root, (key->len ? key->c : ""), (key->len ? (key->len + 1) : sizeof("")), child);
+            add_assoc_zval_warn(root, (key->len ? key->c : ""), (key->len ? (key->len + 1) : sizeof("")), child);
         }
         key->len = 0;
     }
@@ -550,10 +575,10 @@ parse_JSON_ex(JSON_parser jp, zval *z, unsigned short utf16_json[], int length,
                     json_create_zval(&mval, &buf, type, options);
 
                     if (!assoc) {
-                        add_property_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : "_empty_"), (key.len ? (key.len + 1) : sizeof("_empty_")), mval TSRMLS_CC);
+                        add_property_zval_warn(jp->the_zstack[jp->top], (key.len ? key.c : "_empty_"), (key.len ? (key.len + 1) : sizeof("_empty_")), mval TSRMLS_CC);
                         Z_DELREF_P(mval);
                     } else {
-                        add_assoc_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : ""), (key.len ? (key.len + 1) : sizeof("")), mval);
+                        add_assoc_zval_warn(jp->the_zstack[jp->top], (key.len ? key.c : ""), (key.len ? (key.len + 1) : sizeof("")), mval);
                     }
                     key.len = 0;
                     buf.len = 0;
@@ -694,10 +719,10 @@ parse_JSON_ex(JSON_parser jp, zval *z, unsigned short utf16_json[], int length,
                         if (pop(jp, MODE_OBJECT) && push(jp, MODE_KEY)) {
                             if (type != -1) {
                                 if (!assoc) {
-                                    add_property_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : "_empty_"), (key.len ? (key.len + 1) : sizeof("_empty_")), mval TSRMLS_CC);
+                                    add_property_zval_warn(jp->the_zstack[jp->top], (key.len ? key.c : "_empty_"), (key.len ? (key.len + 1) : sizeof("_empty_")), mval TSRMLS_CC);
                                     Z_DELREF_P(mval);
                                 } else {
-                                    add_assoc_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : ""), (key.len ? (key.len + 1) : sizeof("")), mval);
+                                    add_assoc_zval_warn(jp->the_zstack[jp->top], (key.len ? key.c : ""), (key.len ? (key.len + 1) : sizeof("")), mval);
                                 }
                                 key.len = 0;
                             }
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 25 03:01:29 2024 UTC