ID:2693272
 
Resolved
json_decode() would create multiple list entries when given a technically malformed JSON object with duplicate keys.
BYOND Version:514.1554 and 513.1542
Operating System:Windows 10 Pro 64-bit
Web Browser:Firefox 90.0
Applies to:Dream Daemon
Status: Resolved (514.1557)

This issue has been resolved.
Descriptive Problem Summary:
Dream Daemon does not deal properly with key collision in invalid JSON objects. Note that this requires the JSON to be invalid.

Numbered Steps to Reproduce Problem:
1. Decode a JSON object with key collision such as {"key1": "value1", "key1": "value2"}
2. Notice that you now have duplicate entries in the list(the key will show up twice while iterating)

Code Snippet (if applicable) to Reproduce Problem:
world.log << json_encode(json_decode(@|{"key1": "value1", "key1": "value2"}|))
//Output: {"key1": "value2", "key1": "value2"}
//Expected output(one of):
// Invalid JSON runtime error
// {"key1": "value1"}
// {"key1": "value2"}

var/list/L = json_decode(@|{"key1": "value1", "key1": "value2"}|)
for(var/i in L)
world.log << "[i]|[L[i]]"
//Output: key1|value2 \n key1|value2
//Expected output(one of):
// Invalid JSON runtime error
// key1|value1
// key1|value2


Expected Results:
Either:
-The list contains a single entry with the value of the last entry
-The list contains a single entry with the value of the first entry
-A runtime error created by json_decode()

Actual Results:
The list contains two entries of the same key which have the value of the last entry

Does the problem occur:
Every time? Or how often? Every time
In other games? N/A
In other user accounts? Unknown
On other computers? Yes

When does the problem NOT occur?
When theres no key collision

Did the problem NOT occur in any earlier versions? If so, what was the last version that worked? (Visit http://www.byond.com/download/build to download old versions for testing.)
Tested on 514.1554 and 513.1542, issue existed in both

Workarounds:
Validating that there are no conflicting keys after running json_decode if the JSON is from untrusted user input
This should be a runtime error.
The behavior you're seeing makes perfect sense in that it's what you would expect if the list item is added first and then the associated value is set. However I feel the correct BYOND behavior in this case should be for the key to exist once, associated with the second value.

I suppose I could add an arg to json_decode() to enforce JSON's rules more strictly and produce runtime errors in questionable cases. I've just never seen the point. The idea that JSON parsing should be so strict as to fail on single-quoted strings, for instance, is insane to me.
I don't see how making a list which is impossible to create within DM without using /savefile/proc/ImportText() or /proc/json_encode() with tampered input is a logical thing. I feel that if keys conflict, at the very least, BYOND should not be creating multiple entries with the same key. If those procs should cause a runtime if they are ran with tampered input which contains conflicting keys, that's another debate but I don't see how having 2 entries of the same name in what is essentially a dictionary makes any sense.
In response to Alexkar598
No, I agree with you. There shouldn't be two entries with the same key. The behavior you're seeing is basically what would result from this pseudocode:

for(pair in parser)
result += pair.key
result[pair.key] = pair.value

What I think the correct behavior should be is this:

for(pair in parser)
result[pair.key] = pair.value

So I'm working on changing that. JSON says this kind of list with two copies of the same key is invalid, but I just don't see the point in producing a runtime error. At best there might be a reason to allow the JSON parser to use a strict mode.
Also should I open another bug report for the same issue but with /savefile? Basically the same thing except using savefiles instead of json_decode
Lummox JR resolved issue with message:
json_decode() would create multiple list entries when given a technically malformed JSON object with duplicate keys.