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<size_t>::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<const char*>(v.data()) + offset, len);
             }
         }
@@ -6989,6 +7028,7 @@ class basic_json
                     const auto len = static_cast<size_t>(get_from_vector<uint8_t>(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<const char*>(v.data()) + offset, len);
                 }
 
@@ -6997,6 +7037,7 @@ class basic_json
                     const auto len = static_cast<size_t>(get_from_vector<uint16_t>(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<const char*>(v.data()) + offset, len);
                 }
 
@@ -7005,6 +7046,7 @@ class basic_json
                     const auto len = static_cast<size_t>(get_from_vector<uint32_t>(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<const char*>(v.data()) + offset, len);
                 }
 
@@ -7223,6 +7265,7 @@ class basic_json
                 const auto len = static_cast<size_t>(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<const char*>(v.data()) + offset, len);
             }
 
@@ -7231,6 +7274,7 @@ class basic_json
                 const auto len = static_cast<size_t>(get_from_vector<uint8_t>(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<const char*>(v.data()) + offset, len);
             }
 
@@ -7239,6 +7283,7 @@ class basic_json
                 const auto len = static_cast<size_t>(get_from_vector<uint16_t>(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<const char*>(v.data()) + offset, len);
             }
 
@@ -7247,6 +7292,7 @@ class basic_json
                 const auto len = static_cast<size_t>(get_from_vector<uint32_t>(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<const char*>(v.data()) + offset, len);
             }
 
@@ -7255,6 +7301,7 @@ class basic_json
                 const auto len = static_cast<size_t>(get_from_vector<uint64_t>(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<const char*>(v.data()) + offset, len);
             }
 
@@ -7595,6 +7642,11 @@ class basic_json
     */
     static basic_json from_msgpack(const std::vector<uint8_t>& 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<uint8_t>& 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<size_t>::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<const char*>(v.data()) + offset, len);
             }
         }
@@ -6989,6 +7028,7 @@ class basic_json
                     const auto len = static_cast<size_t>(get_from_vector<uint8_t>(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<const char*>(v.data()) + offset, len);
                 }
 
@@ -6997,6 +7037,7 @@ class basic_json
                     const auto len = static_cast<size_t>(get_from_vector<uint16_t>(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<const char*>(v.data()) + offset, len);
                 }
 
@@ -7005,6 +7046,7 @@ class basic_json
                     const auto len = static_cast<size_t>(get_from_vector<uint32_t>(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<const char*>(v.data()) + offset, len);
                 }
 
@@ -7223,6 +7265,7 @@ class basic_json
                 const auto len = static_cast<size_t>(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<const char*>(v.data()) + offset, len);
             }
 
@@ -7231,6 +7274,7 @@ class basic_json
                 const auto len = static_cast<size_t>(get_from_vector<uint8_t>(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<const char*>(v.data()) + offset, len);
             }
 
@@ -7239,6 +7283,7 @@ class basic_json
                 const auto len = static_cast<size_t>(get_from_vector<uint16_t>(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<const char*>(v.data()) + offset, len);
             }
 
@@ -7247,6 +7292,7 @@ class basic_json
                 const auto len = static_cast<size_t>(get_from_vector<uint32_t>(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<const char*>(v.data()) + offset, len);
             }
 
@@ -7255,6 +7301,7 @@ class basic_json
                 const auto len = static_cast<size_t>(get_from_vector<uint64_t>(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<const char*>(v.data()) + offset, len);
             }
 
@@ -7595,6 +7642,11 @@ class basic_json
     */
     static basic_json from_msgpack(const std::vector<uint8_t>& 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<uint8_t>& 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 00000000..8de7c9e5
Binary files /dev/null and b/test/data/cbor_regression/id:000000,sig:06,src:000787,op:havoc,rep:8 differ
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 00000000..d2ae80c7
Binary files /dev/null and b/test/data/cbor_regression/id:000000,sig:06,src:000833,op:havoc,rep:32 differ
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 00000000..d1ef19b5
Binary files /dev/null and b/test/data/cbor_regression/id:000000,sig:06,src:000838,op:havoc,rep:64 differ
diff --git a/test/data/cbor_regression/id:000000,sig:06,src:000846+001064,op:splice,rep:16 b/test/data/cbor_regression/id:000000,sig:06,src:000846+001064,op:splice,rep:16
new file mode 100644
index 00000000..42b437e0
Binary files /dev/null and b/test/data/cbor_regression/id:000000,sig:06,src:000846+001064,op:splice,rep:16 differ
diff --git a/test/data/cbor_regression/id:000000,sig:06,src:000848,op:flip1,pos:0 b/test/data/cbor_regression/id:000000,sig:06,src:000848,op:flip1,pos:0
new file mode 100644
index 00000000..82f3520d
Binary files /dev/null and b/test/data/cbor_regression/id:000000,sig:06,src:000848,op:flip1,pos:0 differ
diff --git a/test/data/cbor_regression/id:000000,sig:06,src:001435,op:havoc,rep:32 b/test/data/cbor_regression/id:000000,sig:06,src:001435,op:havoc,rep:32
new file mode 100644
index 00000000..679a1663
Binary files /dev/null and b/test/data/cbor_regression/id:000000,sig:06,src:001435,op:havoc,rep:32 differ
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 00000000..bb32f698
Binary files /dev/null and b/test/data/cbor_regression/id:000000,sig:06,src:001436,op:havoc,rep:4 differ
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 00000000..e9485810
Binary files /dev/null and b/test/data/cbor_regression/id:000001,sig:06,src:000864+000903,op:splice,rep:2 differ
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 00000000..0e3f141f
Binary files /dev/null and b/test/data/cbor_regression/id:000001,sig:06,src:001330+000569,op:splice,rep:64 differ
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 00000000..0ce68701
Binary files /dev/null and b/test/data/cbor_regression/id:000001,sig:06,src:001413,op:havoc,rep:32 differ
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 00000000..35f3cb59
Binary files /dev/null and b/test/data/cbor_regression/id:000001,sig:06,src:001447,op:havoc,rep:4 differ
diff --git a/test/data/cbor_regression/id:000001,sig:06,src:001465+000325,op:splice,rep:4 b/test/data/cbor_regression/id:000001,sig:06,src:001465+000325,op:splice,rep:4
new file mode 100644
index 00000000..64812d4f
Binary files /dev/null and b/test/data/cbor_regression/id:000001,sig:06,src:001465+000325,op:splice,rep:4 differ
diff --git a/test/data/cbor_regression/id:000002,sig:06,src:000539,op:havoc,rep:8 b/test/data/cbor_regression/id:000002,sig:06,src:000539,op:havoc,rep:8
new file mode 100644
index 00000000..5c537f8d
Binary files /dev/null and b/test/data/cbor_regression/id:000002,sig:06,src:000539,op:havoc,rep:8 differ
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 00000000..0bde9e5d
Binary files /dev/null and b/test/data/cbor_regression/id:000002,sig:06,src:001301,op:havoc,rep:16 differ
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 00000000..0a004d9e
Binary files /dev/null and b/test/data/cbor_regression/id:000002,sig:06,src:001317+000850,op:splice,rep:8 differ
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 00000000..6ff4823a
Binary files /dev/null and b/test/data/cbor_regression/id:000002,sig:06,src:001382,op:havoc,rep:128 differ
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 00000000..d32904ab
Binary files /dev/null and b/test/data/cbor_regression/id:000002,sig:06,src:001413+001036,op:splice,rep:4 differ
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 00000000..156afe0f
Binary files /dev/null and b/test/data/cbor_regression/id:000003,sig:06,src:000846+000155,op:splice,rep:16 differ
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 00000000..e342979e
Binary files /dev/null and b/test/data/cbor_regression/id:000004,sig:06,src:001445,op:havoc,rep:128 differ
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<uint8_t> vec1(
+                    (std::istreambuf_iterator<char>(f_cbor)),
+                    std::istreambuf_iterator<char>());
+                json j1 = json::from_cbor(vec1);
+
+                try
+                {
+                    // step 2: round trip
+                    std::vector<uint8_t> 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")