Commit Graph

20 Commits

Author SHA1 Message Date
user.name
6ccde7f80b bugfix: core/encoding/json leaks the key and value of a malformed object
parse_object_body allocates an object key, then may fail in parse_colon or
parse_value before that key is ever inserted into the object. Its cleanup defer
only walks `obj`, so a key that never got there is unreachable to it. The caller
cannot free it either -- a failed parse returns a nil Value -- so it leaks.

The same applies to the parsed element on the duplicate-key path, and to both on
the out-of-memory path.

JSON5 makes this reachable from ordinary malformed input, because an unquoted
ident is a legal key and anything other than a colon after it fails. Plain JSON
leaks it too, via a quoted key.

before, measured with a tracking allocator over 8 inputs x 2 specs:

	LEAK JSON5  colon fails after unquoted key   1 alloc / 7 bytes
	LEAK JSON   colon fails after quoted key     1 alloc / 2 bytes
	LEAK JSON5  colon fails after quoted key     1 alloc / 2 bytes
	LEAK JSON   value fails after key            1 alloc / 2 bytes
	LEAK JSON5  value fails after key            1 alloc / 2 bytes
	LEAK JSON   nested value fails               2 alloc / 4 bytes
	LEAK JSON5  nested value fails               2 alloc / 4 bytes
	LEAK JSON   deep nesting fails               3 alloc / 6 bytes
	LEAK JSON5  deep nesting fails               3 alloc / 6 bytes
	LEAK JSON   array element fails              1 alloc / 2 bytes
	LEAK JSON5  array element fails              1 alloc / 2 bytes
	total leaked allocations: 17

after, same probe:

	total leaked allocations: 0

The leak scales with nesting depth -- one orphaned key per enclosing object -- so
a service parsing untrusted JSON leaks a little on every malformed request.

The fix marks the key and the element as owned by the loop iteration until they
are stored, and frees them otherwise. The duplicate-key path loses its explicit
delete, which the same mechanism now covers.

Found via odinfmt, which reported a 7-byte leak in a downstream test that parses
`{ broken not json` to check that invalid input is rejected.

Regression test added to tests/core/encoding/json: it reports
`17 leaks and 0 bad frees` without this change and passes with it. The existing
11 tests pass unchanged under -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true.
2026-08-31 11:39:42 -07:00
jkenda
51b80c5a20 encoding/json: marshal enumerated arrays to objects with key-value pairs 2025-02-01 10:32:07 +01:00
Jeroen van Rijn
1a0a6c485d Add comment explaining #4515 test. 2024-11-25 13:47:04 +01:00
Jeroen van Rijn
2dc0187836 Test #4515 2024-11-25 13:16:27 +01:00
Feoramund
1f04f541cf Fix -vet and -strict-style failures in tests 2024-08-26 16:20:08 -04:00
Jeroen van Rijn
fc5ce30f34 Allow json to unmarshal empty struct. 2024-07-21 00:37:11 +02:00
VladPavliuk
3f8712edb0 Merge branch 'master' into json-add-int-key-map-support 2024-07-14 18:22:20 +03:00
VladPavliuk
76fe5d1346 Align ignore syntax of json tags with fmt, cbor 2024-07-14 00:21:05 +03:00
VladPavliuk
64ae99f016 Add support of ignore tag for json.marshal 2024-07-13 14:13:59 +03:00
VladPavliuk
79e2f63182 Small code refactoring in test_core_json 2024-07-13 00:38:58 +03:00
VladPavliuk
39983eaaa4 Remove unused imports in test_core_json 2024-07-13 00:26:54 +03:00
VladPavliuk
dbdad0476d Allow to marshal and unmarshal maps with int keys 2024-07-13 00:07:48 +03:00
Jeroen van Rijn
601df0e8f7 Port tests\core\encoding\json 2024-06-02 14:47:08 -04:00
Rickard Andersson
2e3224a138 testing: add test for Out_Of_Memory return 2023-10-02 15:17:06 +03:00
Abdelrahman Farid
9ed36445b9 Add test for utf8 multibyte strings 2023-09-19 22:18:23 +03:00
Laytan Laats
5d54b710e7 fix #2550 json encoding should use surrogate pairs per RFC7159 2023-05-22 17:22:33 +02:00
Jeroen van Rijn
a30b9b17b3 [json/unmarshal] Fix quoted strings. 2022-04-19 20:32:22 +02:00
Jeroen van Rijn
323e7a2d02 Add JSON unmarshal test. 2022-04-19 15:03:09 +02:00
gingerBill
7203560b06 Fix test 2022-03-24 12:15:03 +00:00
Jeroen van Rijn
6d7217f37a [varint] Add LEB128 decoding + tests
Also make tests in general less spammy: Don't print [PASS] for each successful test, only report failures and progress.
2022-03-08 15:40:00 +01:00