Riot: hangs in cbor parser

Created on 10 Oct 2017  ·  5Comments  ·  Source: RIOT-OS/RIOT

@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

bug

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.

All 5 comments

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.

Was this page helpful?
0 / 5 - 0 ratings