@PyroPeter and I fuzzed the cbor parser with afl and found a few bugs while doing so. See #7707 and #7706. Additionally we found quite a few inputs which triggered hangs in the cbor parsing code. A tarball containing input files triggering hangs in the cbor parser can be found here: http://user.informatik.uni-bremen.de/~tempel/riot-cbor-hangs.tar.xz
BTW: This might sound like a troll but I would honestly suggest that you consider removing this cbor parser entirely: It doesn't properly implement the standard, the code quality is horrible and most importantly it's full of bugs and doesn't seem to have a maintainer who is actively working on this.
@nmeum, can you elaborate a bit more on the code quality issues and problems with RFC compliance?
Regarding RFC compliance: The parser doesn't properly parse the majority of the cbor testvectors. Regarding code quality: We found multiple issue just by fuzzing and going through the code in order to fix those, it just didn't seem very polished.
Here is a patch fixing the hangs (or at least some of them) in the cbor parser:
diff --git a/cbor-afl/cbor.c b/cbor-afl/cbor.c
index fa1aa27..c97457e 100644
--- a/cbor-afl/cbor.c
+++ b/cbor-afl/cbor.c
@@ -989,12 +989,17 @@ static size_t cbor_stream_decode_at(cbor_stream_t *stream, size_t offset, int in
while (is_indefinite ? !cbor_at_break(stream, offset) : i < map_length) {
size_t key_read_bytes, value_read_bytes;
+
offset += key_read_bytes = cbor_stream_decode_at(stream, offset, indent + 1); /* key */
- offset += value_read_bytes = cbor_stream_decode_at(stream, offset, indent + 2); /* value */
+ if (key_read_bytes == 0) {
+ DEBUG("Failed to read key at position %d\n", i);
+ return 0;
+ }
- if (key_read_bytes == 0 || value_read_bytes == 0) {
- DEBUG("Failed to read key-value pair at position %d\n", i);
- break;
+ offset += value_read_bytes = cbor_stream_decode_at(stream, offset, indent + 2); /* value */
+ if (value_read_bytes == 0) {
+ DEBUG("Failed to read value at position %d\n", i);
+ return 0;
}
read_bytes += key_read_bytes + value_read_bytes;
The problem seems to have been that the parser didn't check for errors after parsing key values in maps. So even if a key wasn't found it still invoked cbor_stream_decode_at
for finding a value for a non-existing key.
Not sure if the patch is optimal but at least it doesn't hang anymore…
I've collected all cbor
related issues in #7800. Let's discuss there how to go on with that module.
Most helpful comment
BTW: This might sound like a troll but I would honestly suggest that you consider removing this cbor parser entirely: It doesn't properly implement the standard, the code quality is horrible and most importantly it's full of bugs and doesn't seem to have a maintainer who is actively working on this.