From cf9bf2d9136a9d1c2131f83aa493bb03f36849ab Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 1 Jan 2017 15:28:01 +0100 Subject: [PATCH] :ambulance: fix for #411 and #412 --- src/json.hpp | 11 +++----- src/json.hpp.re2c | 11 +++----- test/src/unit-regression.cpp | 53 ++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 14 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index f8d948f1..5dc8e67c 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -7135,13 +7135,10 @@ class basic_json */ static basic_json from_cbor_internal(const std::vector& v, size_t& idx) { - // make sure reading 1 byte is safe - check_length(v.size(), 1, idx); - // store and increment index const size_t current_idx = idx++; - switch (v[current_idx]) + switch (v.at(current_idx)) { // Integer 0x00..0x17 (0..23) case 0x00: @@ -7322,7 +7319,7 @@ class basic_json case 0x7f: // UTF-8 string (indefinite length) { std::string result; - while (v[idx] != 0xff) + while (v.at(idx) != 0xff) { string_t s = from_cbor_internal(v, idx); result += s; @@ -7418,7 +7415,7 @@ class basic_json case 0x9f: // array (indefinite length) { basic_json result = value_t::array; - while (v[idx] != 0xff) + while (v.at(idx) != 0xff) { result.push_back(from_cbor_internal(v, idx)); } @@ -7518,7 +7515,7 @@ class basic_json case 0xbf: // map (indefinite length) { basic_json result = value_t::object; - while (v[idx] != 0xff) + while (v.at(idx) != 0xff) { std::string key = from_cbor_internal(v, idx); result[key] = from_cbor_internal(v, idx); diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 2faf3858..49bccb02 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -7135,13 +7135,10 @@ class basic_json */ static basic_json from_cbor_internal(const std::vector& v, size_t& idx) { - // make sure reading 1 byte is safe - check_length(v.size(), 1, idx); - // store and increment index const size_t current_idx = idx++; - switch (v[current_idx]) + switch (v.at(current_idx)) { // Integer 0x00..0x17 (0..23) case 0x00: @@ -7322,7 +7319,7 @@ class basic_json case 0x7f: // UTF-8 string (indefinite length) { std::string result; - while (v[idx] != 0xff) + while (v.at(idx) != 0xff) { string_t s = from_cbor_internal(v, idx); result += s; @@ -7418,7 +7415,7 @@ class basic_json case 0x9f: // array (indefinite length) { basic_json result = value_t::array; - while (v[idx] != 0xff) + while (v.at(idx) != 0xff) { result.push_back(from_cbor_internal(v, idx)); } @@ -7518,7 +7515,7 @@ class basic_json case 0xbf: // map (indefinite length) { basic_json result = value_t::object; - while (v[idx] != 0xff) + while (v.at(idx) != 0xff) { std::string key = from_cbor_internal(v, idx); result[key] = from_cbor_internal(v, idx); diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index 421a386c..89b27e0e 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -610,4 +610,57 @@ TEST_CASE("regression tests") CHECK_THROWS_AS(json::from_cbor(vec2), std::out_of_range); CHECK_THROWS_AS(json::from_msgpack(vec2), std::out_of_range); } + + SECTION("issue #411 - Heap-buffer-overflow (OSS-Fuzz issue 366)") + { + // original test case: empty UTF-8 string (indefinite length) + std::vector vec1 {0x7f}; + CHECK_THROWS_AS(json::from_cbor(vec1), std::out_of_range); + + // related test case: empty array (indefinite length) + std::vector vec2 {0x9f}; + CHECK_THROWS_AS(json::from_cbor(vec2), std::out_of_range); + + // related test case: empty map (indefinite length) + std::vector vec3 {0xbf}; + CHECK_THROWS_AS(json::from_cbor(vec3), std::out_of_range); + } + + SECTION("issue #412 - Heap-buffer-overflow (OSS-Fuzz issue 367)") + { + // original test case + std::vector vec + { + 0xab, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x00, 0x00, 0x00, + 0x60, 0xab, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x00, 0x00, 0x00, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xa0, 0x9f, + 0x9f, 0x97, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60 + }; + CHECK_THROWS_AS(json::from_cbor(vec), std::out_of_range); + + // related test case: nonempty UTF-8 string (indefinite length) + std::vector vec1 {0x7f, 0x61, 0x61}; + CHECK_THROWS_AS(json::from_cbor(vec1), std::out_of_range); + + // related test case: nonempty array (indefinite length) + std::vector vec2 {0x9f, 0x01}; + CHECK_THROWS_AS(json::from_cbor(vec2), std::out_of_range); + + // related test case: nonempty map (indefinite length) + std::vector vec3 {0xbf, 0x61, 0x61, 0x01}; + CHECK_THROWS_AS(json::from_cbor(vec3), std::out_of_range); + } }