From 6e129fbfb7a09856659763a13193d6ae1ee6ae0f Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 25 Dec 2016 14:39:08 +0100 Subject: [PATCH 1/2] :memo: some small documentation fixes --- doc/Makefile | 1 + src/json.hpp | 16 ++++++++++------ src/json.hpp.re2c | 16 ++++++++++------ 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/doc/Makefile b/doc/Makefile index 56198923..04a5cc7b 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -57,6 +57,7 @@ doxygen: create_output create_links $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType >@@g' html/*.html $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType >@@g' html/*.html $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType >@@g' html/*.html + $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType >@@g' html/*.html upload: clean doxygen check_output cd html ; ../scripts/git-update-ghpages nlohmann/json diff --git a/src/json.hpp b/src/json.hpp index 23058bee..cb301643 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -3793,7 +3793,7 @@ class basic_json container `c`, the expression `c.front()` is equivalent to `*c.begin()`. @return In case of a structured type (array or object), a reference to the - first element is returned. In cast of number, string, or boolean values, a + first element is returned. In case of number, string, or boolean values, a reference to the value is returned. @complexity Constant. @@ -3836,7 +3836,7 @@ class basic_json @endcode @return In case of a structured type (array or object), a reference to the - last element is returned. In cast of number, string, or boolean values, a + last element is returned. In case of number, string, or boolean values, a reference to the value is returned. @complexity Constant. @@ -4187,10 +4187,14 @@ class basic_json element is not found or the JSON value is not an object, end() is returned. + @note This method always returns @ref end() when executed on a JSON type + that is not an object. + @param[in] key key value of the element to search for @return Iterator to an element with key equivalent to @a key. If no such - element is found, past-the-end (see end()) iterator is returned. + element is found or the JSON value is not an object, past-the-end (see + @ref end()) iterator is returned. @complexity Logarithmic in the size of the JSON object. @@ -4233,6 +4237,9 @@ class basic_json default `std::map` type, the return value will always be `0` (@a key was not found) or `1` (@a key was found). + @note This method always returns `0` when executed on a JSON type that is + not an object. + @param[in] key key value of the element to count @return Number of elements with key @a key. If the JSON value is not an @@ -4792,9 +4799,6 @@ class basic_json object | `{}` array | `[]` - @note Floating-point numbers are set to `0.0` which will be serialized to - `0`. The vale type remains @ref number_float_t. - @complexity Linear in the size of the JSON value. @liveexample{The example below shows the effect of `clear()` to different diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index ac9a3315..6723e75a 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -3793,7 +3793,7 @@ class basic_json container `c`, the expression `c.front()` is equivalent to `*c.begin()`. @return In case of a structured type (array or object), a reference to the - first element is returned. In cast of number, string, or boolean values, a + first element is returned. In case of number, string, or boolean values, a reference to the value is returned. @complexity Constant. @@ -3836,7 +3836,7 @@ class basic_json @endcode @return In case of a structured type (array or object), a reference to the - last element is returned. In cast of number, string, or boolean values, a + last element is returned. In case of number, string, or boolean values, a reference to the value is returned. @complexity Constant. @@ -4187,10 +4187,14 @@ class basic_json element is not found or the JSON value is not an object, end() is returned. + @note This method always returns @ref end() when executed on a JSON type + that is not an object. + @param[in] key key value of the element to search for @return Iterator to an element with key equivalent to @a key. If no such - element is found, past-the-end (see end()) iterator is returned. + element is found or the JSON value is not an object, past-the-end (see + @ref end()) iterator is returned. @complexity Logarithmic in the size of the JSON object. @@ -4233,6 +4237,9 @@ class basic_json default `std::map` type, the return value will always be `0` (@a key was not found) or `1` (@a key was found). + @note This method always returns `0` when executed on a JSON type that is + not an object. + @param[in] key key value of the element to count @return Number of elements with key @a key. If the JSON value is not an @@ -4792,9 +4799,6 @@ class basic_json object | `{}` array | `[]` - @note Floating-point numbers are set to `0.0` which will be serialized to - `0`. The vale type remains @ref number_float_t. - @complexity Linear in the size of the JSON value. @liveexample{The example below shows the effect of `clear()` to different From acb7e0558d2337ad42261ed81e67d37385679285 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 28 Dec 2016 12:09:15 +0100 Subject: [PATCH 2/2] :ambulance: fixed bugs detected by AFL-Fuzz --- src/json.hpp | 57 +++++++++++++ src/json.hpp.re2c | 57 +++++++++++++ ...0,sig:06,src:000223+000677,op:splice,rep:2 | 1 + ...id:000000,sig:06,src:000787,op:havoc,rep:8 | Bin 0 -> 19 bytes ...d:000000,sig:06,src:000833,op:havoc,rep:32 | Bin 0 -> 38 bytes ...d:000000,sig:06,src:000838,op:havoc,rep:64 | Bin 0 -> 842 bytes ...,sig:06,src:000846+001064,op:splice,rep:16 | Bin 0 -> 201 bytes ...id:000000,sig:06,src:000848,op:flip1,pos:0 | Bin 0 -> 263 bytes ...d:000000,sig:06,src:001435,op:havoc,rep:32 | Bin 0 -> 2488 bytes ...id:000000,sig:06,src:001436,op:havoc,rep:4 | Bin 0 -> 2579 bytes ...1,sig:06,src:000864+000903,op:splice,rep:2 | Bin 0 -> 33 bytes ...,sig:06,src:001310+001138,op:splice,rep:32 | 1 + ...,sig:06,src:001330+000569,op:splice,rep:64 | Bin 0 -> 1932 bytes ...d:000001,sig:06,src:001413,op:havoc,rep:32 | Bin 0 -> 1396 bytes ...id:000001,sig:06,src:001447,op:havoc,rep:4 | Bin 0 -> 1839 bytes ...1,sig:06,src:001465+000325,op:splice,rep:4 | Bin 0 -> 475 bytes ...id:000002,sig:06,src:000539,op:havoc,rep:8 | Bin 0 -> 140 bytes ...d:000002,sig:06,src:001301,op:havoc,rep:16 | Bin 0 -> 16 bytes ...2,sig:06,src:001317+000850,op:splice,rep:8 | Bin 0 -> 349 bytes ...:000002,sig:06,src:001382,op:havoc,rep:128 | Bin 0 -> 3116 bytes ...2,sig:06,src:001413+001036,op:splice,rep:4 | Bin 0 -> 395 bytes ...,sig:06,src:000846+000155,op:splice,rep:16 | Bin 0 -> 222 bytes ...:000004,sig:06,src:001445,op:havoc,rep:128 | Bin 0 -> 4382 bytes test/src/unit-cbor.cpp | 78 ++++++++++++++++++ 24 files changed, 194 insertions(+) create mode 100644 test/data/cbor_regression/id:000000,sig:06,src:000223+000677,op:splice,rep:2 create mode 100644 test/data/cbor_regression/id:000000,sig:06,src:000787,op:havoc,rep:8 create mode 100644 test/data/cbor_regression/id:000000,sig:06,src:000833,op:havoc,rep:32 create mode 100644 test/data/cbor_regression/id:000000,sig:06,src:000838,op:havoc,rep:64 create mode 100644 test/data/cbor_regression/id:000000,sig:06,src:000846+001064,op:splice,rep:16 create mode 100644 test/data/cbor_regression/id:000000,sig:06,src:000848,op:flip1,pos:0 create mode 100644 test/data/cbor_regression/id:000000,sig:06,src:001435,op:havoc,rep:32 create mode 100644 test/data/cbor_regression/id:000000,sig:06,src:001436,op:havoc,rep:4 create mode 100644 test/data/cbor_regression/id:000001,sig:06,src:000864+000903,op:splice,rep:2 create mode 100644 test/data/cbor_regression/id:000001,sig:06,src:001310+001138,op:splice,rep:32 create mode 100644 test/data/cbor_regression/id:000001,sig:06,src:001330+000569,op:splice,rep:64 create mode 100644 test/data/cbor_regression/id:000001,sig:06,src:001413,op:havoc,rep:32 create mode 100644 test/data/cbor_regression/id:000001,sig:06,src:001447,op:havoc,rep:4 create mode 100644 test/data/cbor_regression/id:000001,sig:06,src:001465+000325,op:splice,rep:4 create mode 100644 test/data/cbor_regression/id:000002,sig:06,src:000539,op:havoc,rep:8 create mode 100644 test/data/cbor_regression/id:000002,sig:06,src:001301,op:havoc,rep:16 create mode 100644 test/data/cbor_regression/id:000002,sig:06,src:001317+000850,op:splice,rep:8 create mode 100644 test/data/cbor_regression/id:000002,sig:06,src:001382,op:havoc,rep:128 create mode 100644 test/data/cbor_regression/id:000002,sig:06,src:001413+001036,op:splice,rep:4 create mode 100644 test/data/cbor_regression/id:000003,sig:06,src:000846+000155,op:splice,rep:16 create mode 100644 test/data/cbor_regression/id:000004,sig:06,src:001445,op:havoc,rep:128 diff --git a/src/json.hpp b/src/json.hpp index cb301643..913f1966 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -6835,6 +6835,44 @@ class basic_json } } + + /* + @brief checks if given lengths do not exceed the size of a given vector + + To secure the access to the byte vector during CBOR/MessagePack + deserialization, bytes are copied from the vector into buffers. This + function checks if the number of bytes to copy (@a len) does not exceed the + size @s size of the vector. Additionally, an @a offset is given from where + to start reading the bytes. + + This function checks whether reading the bytes is safe; that is, offset is a + valid index in the vector, offset+len + + @param[in] size size of the byte vector + @param[in] len number of bytes to read + @param[in] offset offset where to start reading + + vec: x x x x x X X X X X + ^ ^ ^ + 0 offset len + + @throws out_of_range if `len > v.size()` + */ + static void check_length(const size_t size, const size_t len, const size_t offset) + { + // simple case: requested length is greater than the vector's length + if (len > size or offset > size) + { + throw std::out_of_range("len out of range"); + } + + // second case: adding offset would result in overflow + if ((size > (std::numeric_limits::max() - offset))) + { + throw std::out_of_range("len+offset out of range"); + } + } + /*! @brief create a JSON value from a given MessagePack vector @@ -6886,6 +6924,7 @@ class basic_json const size_t len = v[current_idx] & 0x1f; const size_t offset = current_idx + 1; idx += len; // skip content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast(v.data()) + offset, len); } } @@ -6989,6 +7028,7 @@ class basic_json const auto len = static_cast(get_from_vector(v, current_idx)); const size_t offset = current_idx + 2; idx += len + 1; // skip size byte + content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast(v.data()) + offset, len); } @@ -6997,6 +7037,7 @@ class basic_json const auto len = static_cast(get_from_vector(v, current_idx)); const size_t offset = current_idx + 3; idx += len + 2; // skip 2 size bytes + content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast(v.data()) + offset, len); } @@ -7005,6 +7046,7 @@ class basic_json const auto len = static_cast(get_from_vector(v, current_idx)); const size_t offset = current_idx + 5; idx += len + 4; // skip 4 size bytes + content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast(v.data()) + offset, len); } @@ -7223,6 +7265,7 @@ class basic_json const auto len = static_cast(v[current_idx] - 0x60); const size_t offset = current_idx + 1; idx += len; // skip content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast(v.data()) + offset, len); } @@ -7231,6 +7274,7 @@ class basic_json const auto len = static_cast(get_from_vector(v, current_idx)); const size_t offset = current_idx + 2; idx += len + 1; // skip size byte + content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast(v.data()) + offset, len); } @@ -7239,6 +7283,7 @@ class basic_json const auto len = static_cast(get_from_vector(v, current_idx)); const size_t offset = current_idx + 3; idx += len + 2; // skip 2 size bytes + content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast(v.data()) + offset, len); } @@ -7247,6 +7292,7 @@ class basic_json const auto len = static_cast(get_from_vector(v, current_idx)); const size_t offset = current_idx + 5; idx += len + 4; // skip 4 size bytes + content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast(v.data()) + offset, len); } @@ -7255,6 +7301,7 @@ class basic_json const auto len = static_cast(get_from_vector(v, current_idx)); const size_t offset = current_idx + 9; idx += len + 8; // skip 8 size bytes + content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast(v.data()) + offset, len); } @@ -7595,6 +7642,11 @@ class basic_json */ static basic_json from_msgpack(const std::vector& v) { + if (v.empty()) + { + throw std::invalid_argument("empty vector"); + } + size_t i = 0; return from_msgpack_internal(v, i); } @@ -7652,6 +7704,11 @@ class basic_json */ static basic_json from_cbor(const std::vector& v) { + if (v.empty()) + { + throw std::invalid_argument("empty vector"); + } + size_t i = 0; return from_cbor_internal(v, i); } diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 6723e75a..3b598542 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -6835,6 +6835,44 @@ class basic_json } } + + /* + @brief checks if given lengths do not exceed the size of a given vector + + To secure the access to the byte vector during CBOR/MessagePack + deserialization, bytes are copied from the vector into buffers. This + function checks if the number of bytes to copy (@a len) does not exceed the + size @s size of the vector. Additionally, an @a offset is given from where + to start reading the bytes. + + This function checks whether reading the bytes is safe; that is, offset is a + valid index in the vector, offset+len + + @param[in] size size of the byte vector + @param[in] len number of bytes to read + @param[in] offset offset where to start reading + + vec: x x x x x X X X X X + ^ ^ ^ + 0 offset len + + @throws out_of_range if `len > v.size()` + */ + static void check_length(const size_t size, const size_t len, const size_t offset) + { + // simple case: requested length is greater than the vector's length + if (len > size or offset > size) + { + throw std::out_of_range("len out of range"); + } + + // second case: adding offset would result in overflow + if ((size > (std::numeric_limits::max() - offset))) + { + throw std::out_of_range("len+offset out of range"); + } + } + /*! @brief create a JSON value from a given MessagePack vector @@ -6886,6 +6924,7 @@ class basic_json const size_t len = v[current_idx] & 0x1f; const size_t offset = current_idx + 1; idx += len; // skip content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast(v.data()) + offset, len); } } @@ -6989,6 +7028,7 @@ class basic_json const auto len = static_cast(get_from_vector(v, current_idx)); const size_t offset = current_idx + 2; idx += len + 1; // skip size byte + content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast(v.data()) + offset, len); } @@ -6997,6 +7037,7 @@ class basic_json const auto len = static_cast(get_from_vector(v, current_idx)); const size_t offset = current_idx + 3; idx += len + 2; // skip 2 size bytes + content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast(v.data()) + offset, len); } @@ -7005,6 +7046,7 @@ class basic_json const auto len = static_cast(get_from_vector(v, current_idx)); const size_t offset = current_idx + 5; idx += len + 4; // skip 4 size bytes + content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast(v.data()) + offset, len); } @@ -7223,6 +7265,7 @@ class basic_json const auto len = static_cast(v[current_idx] - 0x60); const size_t offset = current_idx + 1; idx += len; // skip content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast(v.data()) + offset, len); } @@ -7231,6 +7274,7 @@ class basic_json const auto len = static_cast(get_from_vector(v, current_idx)); const size_t offset = current_idx + 2; idx += len + 1; // skip size byte + content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast(v.data()) + offset, len); } @@ -7239,6 +7283,7 @@ class basic_json const auto len = static_cast(get_from_vector(v, current_idx)); const size_t offset = current_idx + 3; idx += len + 2; // skip 2 size bytes + content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast(v.data()) + offset, len); } @@ -7247,6 +7292,7 @@ class basic_json const auto len = static_cast(get_from_vector(v, current_idx)); const size_t offset = current_idx + 5; idx += len + 4; // skip 4 size bytes + content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast(v.data()) + offset, len); } @@ -7255,6 +7301,7 @@ class basic_json const auto len = static_cast(get_from_vector(v, current_idx)); const size_t offset = current_idx + 9; idx += len + 8; // skip 8 size bytes + content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast(v.data()) + offset, len); } @@ -7595,6 +7642,11 @@ class basic_json */ static basic_json from_msgpack(const std::vector& v) { + if (v.empty()) + { + throw std::invalid_argument("empty vector"); + } + size_t i = 0; return from_msgpack_internal(v, i); } @@ -7652,6 +7704,11 @@ class basic_json */ static basic_json from_cbor(const std::vector& v) { + if (v.empty()) + { + throw std::invalid_argument("empty vector"); + } + size_t i = 0; return from_cbor_internal(v, i); } diff --git a/test/data/cbor_regression/id:000000,sig:06,src:000223+000677,op:splice,rep:2 b/test/data/cbor_regression/id:000000,sig:06,src:000223+000677,op:splice,rep:2 new file mode 100644 index 00000000..e30ed176 --- /dev/null +++ b/test/data/cbor_regression/id:000000,sig:06,src:000223+000677,op:splice,rep:2 @@ -0,0 +1 @@ +{ \ No newline at end of file diff --git a/test/data/cbor_regression/id:000000,sig:06,src:000787,op:havoc,rep:8 b/test/data/cbor_regression/id:000000,sig:06,src:000787,op:havoc,rep:8 new file mode 100644 index 0000000000000000000000000000000000000000..8de7c9e50d18d64f7807ba158718d1f71895dcbb GIT binary patch literal 19 Ucmb>a4*~zI8JHLtY#4w50DwOT>;M1& literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000000,sig:06,src:000833,op:havoc,rep:32 b/test/data/cbor_regression/id:000000,sig:06,src:000833,op:havoc,rep:32 new file mode 100644 index 0000000000000000000000000000000000000000..d2ae80c771595f1dd59d700664577524eb5b6c78 GIT binary patch literal 38 ncmb>a4+Yz{ZCko+8v~FsY*hH0R#}`{B9NAmvAB3qiNr4e3C$Nr literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000000,sig:06,src:000838,op:havoc,rep:64 b/test/data/cbor_regression/id:000000,sig:06,src:000838,op:havoc,rep:64 new file mode 100644 index 0000000000000000000000000000000000000000..d1ef19b507738ecf9c8e939347afc9087aad6876 GIT binary patch literal 842 zcmb>a4+Yz{$)Db~EwwbYcH+c|^OvrjxCRUqz~oj20SI@^|MwFoPMEl8B2ZVup>5l? zIcx@MO4*SF)C2^Ltq}Tri3G#{2FAoJ=bXmcYz2?hq6UUU28Hyzs?@xav}6VbCWay_ zl7JCb)j?QAQ3Z>D76NTeElSBt%uP)xF3p3=V>c32GkLs{%#ywm?bHf|U`fU=_3}V# zvvU(O^Ww`h8Gsa4+Y!6fB{6-9|Do5w{1(!O|6{>0&6F(K>}OX#DIW3n4CBfs(v$2eM)K)SpCFC u5Oo#;oa4+Y!6fB{6-9|Do5w{1%;O|6{>0&6F(K>}OhY_KGVfN9zc)RdB%1QBn9N}n&0 z_?41al9=V3lbM{Y;E`I?z>vtGke-*DnpcvR3?x#EQi?OHQYBOpbMsS*OY;mHGyKz9 zi&IM^(lRniBpJWd%O~chX6Ghm=Eaw1=B31xr}G8RB&QwU2&>{H!go0b6(hUX^LPGdafk>dNZ4(a0gz3!N-GSMi?aY+!s*&o| zo6*D@#Df?A0sjR42Tz_fF~JLHjL|x~Eu}PqH3ISAoaTG;_RV|W+q`d{)#i&!d9y^2 zLJQpOGYzRs8z}`MFheBe@Rs7`x`CDX!mLr{nZqV9@L@-7)kg>Sc0a!{SH3OX*tsx9 zc`&I$+oKE-VBuqmu9^0fl7IyEW&)Q6P~c^*_)UZ?J4^p@?Z=W(VN{3G1=R`d7c+(bM^11&Rp@+(O?DYiAyH7DcOGCx$~*tstnsV-&uSY<#-Ut3~9=uty?K?Qla7k zAktqsD6ZLDufIz^lbY8uq(*4nFbplFI$VZCm(xV@bF5EW5B;C5zoavemSvDA%3@z; Gb3Xwc-m0Vk literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000000,sig:06,src:001436,op:havoc,rep:4 b/test/data/cbor_regression/id:000000,sig:06,src:001436,op:havoc,rep:4 new file mode 100644 index 0000000000000000000000000000000000000000..bb32f698895c0584b1476a95e8db9b6272bef2f5 GIT binary patch literal 2579 zcmdT`&uZFeee0V(Mq?y>hw4> ztfj)L0yIvC83Q_TQieGH&?v7DzHvs*NSMf(cR)f6&&|W_i)UWG`1?<1{onS5=ifGj zN=}-z6A8&U$TSk{2dA@W5SaF(Ye^^)SW})dc-kA>ymn>or`07_=Z-q}QppT-wDJK_ z>89M;eeUlzr`Du6cV?G8pa1Oe?3ZDOFWqtf>eqXp9l@_<#^3)~=nmu>aG|NI)HLe# z#k~COP0(6!p!P@W=rccp9>n=q*fmN+?X0vsxn=J^Ynff@bI)(Y!q*B_U>Z1(2%54q zT({M3F1CJbcYBTb^XJZ8x=L{#TN1KNX#%CYJGg=M$iyoD)eZ|`*wf74s681L9)E+J zJr)*7p2QYOj%w9c0m}wc8}Pt5p2uy$t~h#8huA(+n(H!ikHm0e2zne05mvgL7sw%C zLupzOnptU5Dc&0P4Oz`sNg%>ysSueSH#G1oV`y5GQ`CHTzPc={l}d$>i-crJ6j}UeU2mF#L8Z2zN~&}Aozh|5SAT6! z>Nm$IM&r=d^DdigO(vFj9cq5j@ac2kmJoBm;?Y z_eS}YtQuPWwCpUMUMkh9Me{7lPRw%7&{V29nj*kLq1hRWWH~!i{z~p}HNwF&rp2~W`Zh_GW^aNuJ{{+F_u*Bc&3FyiVZ_75HVtih%R!_3 NefxuDbw9>>^9`wVbX@=d literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000001,sig:06,src:000864+000903,op:splice,rep:2 b/test/data/cbor_regression/id:000001,sig:06,src:000864+000903,op:splice,rep:2 new file mode 100644 index 0000000000000000000000000000000000000000..e94858106169ac59d0330ea1f59fcc42f09d2f2e GIT binary patch literal 33 ecmZ3OQa^bX!-NUe4Q2jmtlVHwUteGS9|i#A<`C`x literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000001,sig:06,src:001310+001138,op:splice,rep:32 b/test/data/cbor_regression/id:000001,sig:06,src:001310+001138,op:splice,rep:32 new file mode 100644 index 00000000..92079a80 --- /dev/null +++ b/test/data/cbor_regression/id:000001,sig:06,src:001310+001138,op:splice,rep:32 @@ -0,0 +1 @@ +{et \ No newline at end of file diff --git a/test/data/cbor_regression/id:000001,sig:06,src:001330+000569,op:splice,rep:64 b/test/data/cbor_regression/id:000001,sig:06,src:001330+000569,op:splice,rep:64 new file mode 100644 index 0000000000000000000000000000000000000000..0e3f141f863bb079b063807cf5accd2f27fadc2f GIT binary patch literal 1932 zcmeHIy-ve05VlYsfHz=bth4X}s8Xg@0yR4v$tAe8!z&SihA-D}NXYksfh zZ^r%gVUQ~6EERDR(#aTem2`T8LYV`trRBMlnnK3|1F4PC_*zD2vZJ4(dxIA*e_#<1 z40SSsY%Ff^ob`~Pm<*bCNvLM>l<)-TQd7?NEh#cUXua0h4s`Y7D9fuGmQ(%$hfzmd literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000001,sig:06,src:001413,op:havoc,rep:32 b/test/data/cbor_regression/id:000001,sig:06,src:001413,op:havoc,rep:32 new file mode 100644 index 0000000000000000000000000000000000000000..0ce68701c4269554399e96dd393c063e3493f186 GIT binary patch literal 1396 zcmc(fy>1gh5XaBBA{C_@q^ppSz$i!{WQ0UwLcj|4VH=@9LDsi(zBPBZ=bf?dtRQSU zBpM1T8dA~l0z3;(Kt&ah5QW)W8!P^Z3kuk3=Qp!Eqn-cGyQI>nRqZBc#P(!6CjrTJ z7!fGzcFYhrk4UyU;F6u#i6GzJv>|{HzR}U>#>MZ)KR(+BziQXMoGl3%ZBgv_B48YX z*ca@Q?Q9VOQ?9==Xp0EyvLy*Gw7QRXwlCkW-o2s>DDqYuFak$O7Z9Z?2gCXGYTh)~ z;dpKt_IgF!49$g4jh`prEKqOWo;0R=SY&6cMRL0RY&h(%TbbkdnSfFsTvb8M41?{=&yT_zxKUYdGh*7`tRU}EY<$Hd{5Rn`?h6SYXkm^ zlbOC(UFos3oAutBABi#cnZGByVr{{HTo~Z5yIZbsT XBGS3D8Q8;xiw>uMgr!9{#QfLaIWB|R literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000001,sig:06,src:001447,op:havoc,rep:4 b/test/data/cbor_regression/id:000001,sig:06,src:001447,op:havoc,rep:4 new file mode 100644 index 0000000000000000000000000000000000000000..35f3cb597438e5ac05686abe6588f769b8e233a4 GIT binary patch literal 1839 zcmcJQ&ubGw6vq>LvLJZOMO*|61)HU|LP;r7(;pgQ5|fCCm(K3I%}zSIlgvz-je?DM z^y0yj7kly|UOf3H^l$Jl@F1RAK`hp{n@vp8h+1?mnfJ}in>X)$-p-45u2L)*RZ29; zi&|2E(ng7B4bnFnM5*~bEv!1&+GrbXrd?y+01h5})_dKh*~5b`?~Sc*#cLnVW|;6- zb))1mPAKq(%g7a@w5k;lX}jy48uOtnETPqm)x5WUWA0XA!<3PbrdER!4J9dTP)f)w z-yI!KM$O22bUZR9tQeCN!vyVrNslKxo|-J5P}?Vz-Dd;o^_!JS zlb3-qiFL)YVYQc{0u*;ZN=5+zaJQ6AY!|BFMSrP^77|idc}U9raDG?vV7X2$JL551 z3MCw!QBAHu?pQKon)zaOHGi{Msb=OE7Z#S+aGyms7$3OQj*yie9ezlMO1s(<(Wxa; zgH}}%dpot?iWPes#VVM9k?DHwxYr7CXh&Vj?tAm?z&Ba3VR4!e(b4l*Da{vg+U&2 z+|#2NlP9zgT=f-YdSO;L=sBBXPX!l+tfg(?{Je9{#iZvzO}O*Bcy#-dv0pmf9OO)u z!I7Zc>9OMV+|u^Z??&JEKXrO^gc%=BFw&D1eu@Th#-#9wB;MO?%yb@$7eX0a94Zc{;wuN_hTs%ru-M=EDyBf2ZLpk1Lk((va+i(HlC`+JNijke zMstF!IGR(FHFFBGo@zI7{D)-G(Qb;!Vw1ZG`+DD_ZNL9}$kyOZ=n9C0|A}^(6ngipP Xw8GTP^qdk&qc16WiMcu1h7!L3r4T|{ literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000002,sig:06,src:001301,op:havoc,rep:16 b/test/data/cbor_regression/id:000002,sig:06,src:001301,op:havoc,rep:16 new file mode 100644 index 0000000000000000000000000000000000000000..0bde9e5dafffd9b12824980438be7148cc5b4cbd GIT binary patch literal 16 OcmeC4QvDwR7=!?C;0&Sw literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000002,sig:06,src:001317+000850,op:splice,rep:8 b/test/data/cbor_regression/id:000002,sig:06,src:001317+000850,op:splice,rep:8 new file mode 100644 index 0000000000000000000000000000000000000000..0a004d9e5d88a9143366bb06355f4802b8978194 GIT binary patch literal 349 zcmbPI{hvs1k4SY?SM~;I;o-dL3m6BMJnB|<4nVhZQky_NikjS8r zo|l`NSCWw50=N G%P#;ZUH69o literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000002,sig:06,src:001382,op:havoc,rep:128 b/test/data/cbor_regression/id:000002,sig:06,src:001382,op:havoc,rep:128 new file mode 100644 index 0000000000000000000000000000000000000000..6ff4823ae78f780f81f09637fa08249459c2338e GIT binary patch literal 3116 zcmZ3OGHdcIh6xj_8_N9CSaOQxfC&fTihD=^ zmJ%^tfy3DRUvO8cB0Cy~a;PgFg01&Mcv=CJu6MMh2i|+M{4J z1V%$(Gz11o2!IMPXxWP>{NN>izN8&e5ucl8EdW*zD$+f`HGmqDG@=Gk0GH(m^Pr6c zgaS}$>mQ$5VwJKZBm+`8LTYUXNUaU4$cV10vcb(2j7s7$j#3}exv8Y(RH1(cqw1~%i68hNn1;TEs0`+oC0P`eK(1T%FDknsW7PGcy~EXhzXRLD)u zO-e0NvWiwpEH7fH)Bp=xDtP6j=B8$pD8<(1DikXeD6p`yvAa3?xVd|HdU^Z!`uPV4 Q1_g(N&g}dzz`*bU07#X%a{vGU literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000002,sig:06,src:001413+001036,op:splice,rep:4 b/test/data/cbor_regression/id:000002,sig:06,src:001413+001036,op:splice,rep:4 new file mode 100644 index 0000000000000000000000000000000000000000..d32904abc2805ce51238f7023c52ab0f6152b0f2 GIT binary patch literal 395 zcmbPI?iK9srx22oSd!?IpU#+{T3n(KkXTZZT9l_ykXT%7xS%9IDJwO(M4?=vJhLQ2 z!B8PJCp9;Hdb)f138V78{F0|P^1PKA7eVe0gX!Xt~-fC3^Y z0%|$G4;=P#ZGV0s&o?DAJ+masz|hDzH!nRiF()%UFE=HxB(3IYDllwQN)vNaQ;JI& Q8PYTS)6$AlOC){)06NLQRsaA1 literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000003,sig:06,src:000846+000155,op:splice,rep:16 b/test/data/cbor_regression/id:000003,sig:06,src:000846+000155,op:splice,rep:16 new file mode 100644 index 0000000000000000000000000000000000000000..156afe0f177baf655b54b410a2128abd6b8002f9 GIT binary patch literal 222 zcmb>a4+XUofnf65i7(bnYy`5-mq`3dNi0dsa?Z(2&Q|b9Eoxv$WKc-Y%T3KINh{Ax zDap`f{F0WDnwjpDotsf2$@nEDFEJO$PRz`UFVD%%q_?{qTrpM zmzJ1Rnv+cz05x?4To@XD$phMKu6|zg48zX2k*_(E67XF hOw7rIx+WOtq|_pi^{FYvrFn)r89?KTQ+p(S0RTe0Vu%0$ literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000004,sig:06,src:001445,op:havoc,rep:128 b/test/data/cbor_regression/id:000004,sig:06,src:001445,op:havoc,rep:128 new file mode 100644 index 0000000000000000000000000000000000000000..e342979eb1b875aadac159e722c4259527aec25c GIT binary patch literal 4382 zcmeHKPmkL~6rTvhp{E|h0V$VqKs3?P3Zbl!*zTXgDrCbZ)p9}Ei9NPwGw~!dlg6Q? zUdoOCLWm>ni33)23Cp)x75c{Zah@Hb3zPN8kI&=IVC@qk7I47+?hN{{GDee5ZbDL zuV)2`R-K(Sc_Ygi`q1g}vHwTH9l+i`=S-Fvw}nL+X$kB~i-BhXT#(|Uo{9g)b%R^jGjyg0?gnJ{hznCho>~i%|2>n4u{D&t`_0Cm(j*oh zGBx>PX;z;nMrLK;-%aR|`i<|Oot>GN2Gb}%Ao7q{;(h5{l7Xv5dVPjfxSVd$9Q~D) zuaZVuH|ca;+uSXh-b)5|En2_H3J4)Fu2L7iOu4(I`VEINY!cRYD1Non*fJ%-!fZngQ8s(G6}k7R4zD4&L8Rp34+dN4y~u@KHu!I+lk(A6 z($Uz~>$r<2{$#Rn9D2D#+BX@O5<^f@K}-g~jl(OJ*U|@kLS3q^_OZadpSp0^HEslP zdsiw$DJl$1R#ChMUNCG~+196;&W#dEk{Ej0S&yF4BT0 zME`y0NN$6nXv2k;_J*#m!oh7K1T_IBlyjUYyicI;LcDm5X-L@A*l|lRZ}Y_L7}Xv% z1ee@WRXJdi2>431Qm7qlZ`IyDXtt^w*RNgM+<|!=yr=PLTFc7fqM4{KS$0$pk~qLA zn+!E_b&EgeAlJ04L--o#$e1E`T0&QISQWn}ssd+JMLQ2Mn65ceMf=`oG%}8e-gB=QAYu$Yw*)b7jG;a(45*xvUs9eV zbVJLTLH7)c*T>++Vo9`#xqs=riIy02y^CuTL5Q!XWT8!TpiP8bYjgNDBu%p=VI7{MDt;{nKi-4=G z{p-qFXq)@9ObW5{EV&3m1(Zc`5jsT?#m(X(c@!3*=QXcRQP@}3q_6?|&A8q$xR7|) zBl7zoAirOdV^%GSlb)jUJei!IBea-sCLCCN6?zNQEfqBJg&*w! N4a8pAxG&4w{{SA`b1?t_ literal 0 HcmV?d00001 diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp index 14944cff..5769ac98 100644 --- a/test/src/unit-cbor.cpp +++ b/test/src/unit-cbor.cpp @@ -1186,6 +1186,84 @@ TEST_CASE("single CBOR roundtrip") } } +TEST_CASE("CBOR regressions") +{ + SECTION("fuzz test results") + { + /* + The following test cases were found during a two-day session with + AFL-Fuzz. As a result, empty byte vectors and excessive lengths are + detected. + */ + for (std::string filename : + { + "test/data/cbor_regression/id:000000,sig:06,src:000223+000677,op:splice,rep:2", + "test/data/cbor_regression/id:000000,sig:06,src:000787,op:havoc,rep:8", + "test/data/cbor_regression/id:000000,sig:06,src:000833,op:havoc,rep:32", + "test/data/cbor_regression/id:000000,sig:06,src:000838,op:havoc,rep:64", + "test/data/cbor_regression/id:000000,sig:06,src:000846+001064,op:splice,rep:16", + "test/data/cbor_regression/id:000000,sig:06,src:000848,op:flip1,pos:0", + "test/data/cbor_regression/id:000000,sig:06,src:001435,op:havoc,rep:32", + "test/data/cbor_regression/id:000000,sig:06,src:001436,op:havoc,rep:4v", + "test/data/cbor_regression/id:000001,sig:06,src:000864+000903,op:splice,rep:2", + "test/data/cbor_regression/id:000001,sig:06,src:001310+001138,op:splice,rep:32", + "test/data/cbor_regression/id:000001,sig:06,src:001330+000569,op:splice,rep:64", + "test/data/cbor_regression/id:000001,sig:06,src:001413,op:havoc,rep:32", + "test/data/cbor_regression/id:000001,sig:06,src:001447,op:havoc,rep:4", + "test/data/cbor_regression/id:000001,sig:06,src:001465+000325,op:splice,rep:4", + "test/data/cbor_regression/id:000002,sig:06,src:000539,op:havoc,rep:8", + "test/data/cbor_regression/id:000002,sig:06,src:001301,op:havoc,rep:16", + "test/data/cbor_regression/id:000002,sig:06,src:001317+000850,op:splice,rep:8", + "test/data/cbor_regression/id:000002,sig:06,src:001382,op:havoc,rep:128", + "test/data/cbor_regression/id:000002,sig:06,src:001413+001036,op:splice,rep:4", + "test/data/cbor_regression/id:000003,sig:06,src:000846+000155,op:splice,rep:16", + "test/data/cbor_regression/id:000004,sig:06,src:001445,op:havoc,rep:128" + }) + { + CAPTURE(filename); + + try + { + // parse CBOR file + std::ifstream f_cbor(filename, std::ios::binary); + std::vector vec1( + (std::istreambuf_iterator(f_cbor)), + std::istreambuf_iterator()); + json j1 = json::from_cbor(vec1); + + try + { + // step 2: round trip + std::vector vec2 = json::to_cbor(j1); + + // parse serialization + json j2 = json::from_cbor(vec2); + + // deserializations must match + CHECK(j1 == j2); + } + catch (const std::invalid_argument&) + { + // parsing a CBOR serialization must not fail + CHECK(false); + } + } + catch (const std::invalid_argument&) + { + // parse errors are ok, because input may be random bytes + } + catch (const std::out_of_range&) + { + // parse errors are ok, because input may be random bytes + } + catch (const std::domain_error&) + { + // parse errors are ok, because input may be random bytes + } + } + } +} + TEST_CASE("CBOR roundtrips", "[hide]") { SECTION("input from flynn")