Details
-
Bug
-
Status: Open (View Workflow)
-
Major
-
Resolution: Unresolved
-
10.11, 11.4, 11.8, 12.3, 13.0
-
None
Description
JSON_KEYS returns each key of an object once. A key whose name
contains an escaped quote is returned as many times as it appears.
SELECT JSON_KEYS('{"a\"b":1,"a\"b":2}') AS v; |
v
|
["a\"b", "a\"b"] |
Every other escape folds correctly:
SELECT JSON_KEYS('{"a\\b":1,"a\\b":2}') AS backslash; -- ["a\\b"] |
SELECT JSON_KEYS('{"a\nb":1,"a\nb":2}') AS newline; -- ["a\nb"] |
How to repeat
SELECT JSON_KEYS('{"a\"b":1,"a\"b":2}') AS two_of_one_key; |
SELECT JSON_LENGTH(JSON_KEYS('{"a\"b":1,"a\"b":2}')) AS how_many; |
-- 2, where the object has one key name
|
 |
SELECT JSON_KEYS('{"x":1,"a\"b":2,"y":3,"a\"b":4,"z":5}') AS in_company; |
-- ["x", "a\"b", "y", "a\"b", "z"]
|
Root cause
`check_key_in_list()` walks the array of keys built so far, looking for
a bare quote as the end of each key. A key containing an escaped quote
ends early by that rule: the comparison is then made over a prefix, and
the walk resynchronises to an offset that is not the start of the next
key, so the key already in the list is never recognised.
The function's own comment states the assumption that fails: *"It
utilizes the fact the resulting string is in specific format:
["key1", "key2"...]"*.
Note
The same walk contains an unbounded scan for the closing quote. Several
escaped-key layouts were traced by hand without going past the end of
the buffer and no out-of-bounds claim is made here, but given that the
terminator assumption is now known to be wrong, *this is worth a run
under ASAN before the report is closed*.
Affected versions
JSON_KEYS was added in 10.2.3. The de-duplication itself was
added for MDEV-12789, and this is a hole in that fix.
Verified on 10.11 only (10.11.19-MariaDB-debug, commit 1dab253482d).
Other branches were not tested.
Note
Found while auditing the JSON functions against their documented
contracts. None for escaped keys. The de-duplication is pinned
only with plain keys at func_json.test:159-160;
func_json_keys_typed.test:58-61 uses two distinct keys, so the
comparison path is never taken.
Attachments
Issue Links
- split from
-
MDEV-40642 Project "JSON Phoenix" (placeholder)
-
- Open
-