From 9abf8e043fcca2e41b093db5d39e7a2f0a53e80a Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Sat, 14 Nov 2020 21:00:06 -0800 Subject: [PATCH 1/2] Clamp 32-bit varints to 5 bytes to fix a fuzz failure. --- benchmarks/compare.py | 4 +++- upb/decode.c | 17 ++++++++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/benchmarks/compare.py b/benchmarks/compare.py index 48f9704e11..9bdf787138 100755 --- a/benchmarks/compare.py +++ b/benchmarks/compare.py @@ -45,7 +45,9 @@ def Benchmark(outbase, bench_cpu=True, runs=12, fasttable=False): # Translate into the format expected by benchstat. with open(outbase + ".txt", "w") as f: for run in bench_json["benchmarks"]: - name = re.sub(r'^BM_', 'Benchmark', run["name"]) + name = run["name"] + name = name.replace(" ", "") + name = re.sub(r'^BM_', 'Benchmark', name) if name.endswith("_mean") or name.endswith("_median") or name.endswith("_stddev"): continue values = (name, run["iterations"], run["cpu_time"]) diff --git a/upb/decode.c b/upb/decode.c index 26a8d42315..d2ba8c25ea 100644 --- a/upb/decode.c +++ b/upb/decode.c @@ -221,11 +221,18 @@ static const char *decode_varint64(upb_decstate *d, const char *ptr, UPB_FORCEINLINE static const char *decode_varint32(upb_decstate *d, const char *ptr, uint32_t *val) { - uint64_t u64; - ptr = decode_varint64(d, ptr, &u64); - if (u64 > UINT32_MAX) decode_err(d); - *val = (uint32_t)u64; - return ptr; + uint64_t byte = (uint8_t)*ptr; + if (UPB_LIKELY((byte & 0x80) == 0)) { + *val = byte; + return ptr + 1; + } else { + const char *start = ptr; + decode_vret res = decode_longvarint64(ptr, byte); + ptr = res.ptr; + *val = res.val; + if (!ptr || *val > UINT32_MAX || ptr - start > 5) decode_err(d); + return ptr; + } } static void decode_munge(int type, wireval *val) { From 8d670d8aea450abf3563a8e1b71c675ecec762c7 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Sun, 15 Nov 2020 08:56:32 -0800 Subject: [PATCH 2/2] Renamed decode_varint32() to decode_tag(). --- upb/decode.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/upb/decode.c b/upb/decode.c index d2ba8c25ea..a5f0666fa8 100644 --- a/upb/decode.c +++ b/upb/decode.c @@ -219,7 +219,7 @@ static const char *decode_varint64(upb_decstate *d, const char *ptr, } UPB_FORCEINLINE -static const char *decode_varint32(upb_decstate *d, const char *ptr, +static const char *decode_tag(upb_decstate *d, const char *ptr, uint32_t *val) { uint64_t byte = (uint8_t)*ptr; if (UPB_LIKELY((byte & 0x80) == 0)) { @@ -552,7 +552,7 @@ static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg, int op; UPB_ASSERT(ptr < d->limit_ptr); - ptr = decode_varint32(d, ptr, &tag); + ptr = decode_tag(d, ptr, &tag); field_number = tag >> 3; wire_type = tag & 7; @@ -580,13 +580,15 @@ static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg, break; case UPB_WIRE_TYPE_DELIMITED: { int ndx = field->descriptortype; + uint64_t size; if (_upb_isrepeated(field)) ndx += 18; - ptr = decode_varint32(d, ptr, &val.size); - if (val.size >= INT32_MAX || - ptr - d->end + (int32_t)val.size > d->limit) { + ptr = decode_varint64(d, ptr, &size); + if (size >= INT32_MAX || + ptr - d->end + (int32_t)size > d->limit) { decode_err(d); /* Length overflow. */ } op = delim_ops[ndx]; + val.size = size; break; } case UPB_WIRE_TYPE_START_GROUP: