From 057058f58d821febc946829131a2e2d8dd2b3c37 Mon Sep 17 00:00:00 2001 From: Nicolas Iooss Date: Thu, 13 Mar 2025 15:35:03 +0100 Subject: [PATCH] CBOR-to-JSON: fix memory leak when parsing invalid CBOR When function text_string_to_escaped successfully parses a string and fails to parse the next value (cbor_value_finish_string_iteration returns an error), it correctly propagates the error but the string is never freed. This can be reproduced with: make CC='clang -g -fsanitize=address' printf '\x82\x60\xff' | ./bin/cbordump -j clang's Address Sanitizer reports: ================================================================= ==20317==ERROR: LeakSanitizer: detected memory leaks Direct leak of 1 byte(s) in 1 object(s) allocated from: #0 0x560b654b9916 in __interceptor_realloc (/tinycbor/bin/cbordump+0xa4916) (BuildId: f9933666b5d987b21f68c2887de4aebe93bc2bef) #1 0x560b654f5c18 in escape_text_string /tinycbor/src/cbortojson.c:331:15 #2 0x560b654f3e29 in text_string_to_escaped /tinycbor/src/cbortojson.c:377:19 #3 0x560b654f267d in value_to_json /tinycbor/src/cbortojson.c:674:19 #4 0x560b654f34c2 in array_to_json /tinycbor/src/cbortojson.c:545:25 #5 0x560b654f2085 in value_to_json /tinycbor/src/cbortojson.c:627:19 #6 0x560b654f1baf in cbor_value_to_json_advance /tinycbor/src/cbortojson.c:816:12 #7 0x560b654ea928 in dumpFile /tinycbor/tools/cbordump/cbordump.c:76:19 #8 0x560b654ead2b in main /tinycbor/tools/cbordump/cbordump.c:149:9 #9 0x7fa9d7629d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16 SUMMARY: AddressSanitizer: 1 byte(s) leaked in 1 allocation(s). Fix this by freeing the string when cbor_value_finish_string_iteration fails. Fixes: e072bc1d7872 ("CBOR-to-JSON: do properly escape JSON strings") --- src/cbortojson.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cbortojson.c b/src/cbortojson.c index e39f0b90..a19f5f8a 100644 --- a/src/cbortojson.c +++ b/src/cbortojson.c @@ -381,7 +381,9 @@ static CborError text_string_to_escaped(char **str, CborValue *it) /* success */ if (!*str) *str = strdup(""); // wasteful, but very atypical - return cbor_value_finish_string_iteration(it); + err = cbor_value_finish_string_iteration(it); + if (likely(err == CborNoError)) + return CborNoError; } cbor_free(*str);