diff --git a/3rdParty/velocypack/include/velocypack/Iterator.h b/3rdParty/velocypack/include/velocypack/Iterator.h index a6fe3db147..724dc5f059 100644 --- a/3rdParty/velocypack/include/velocypack/Iterator.h +++ b/3rdParty/velocypack/include/velocypack/Iterator.h @@ -157,6 +157,7 @@ class ArrayIterator { _current = nullptr; if (_size > 0) { auto h = _slice.head(); + VELOCYPACK_ASSERT(h != 0x01); // no empty array allowed here if (h == 0x13) { _current = _slice.at(0).start(); } else { @@ -194,6 +195,7 @@ class ObjectIterator { if (_size > 0) { auto h = slice.head(); + VELOCYPACK_ASSERT(h != 0x0a); // no empty object allowed here if (h == 0x14) { _current = slice.keyAt(0, false).start(); } else if (useSequentialIteration) { diff --git a/3rdParty/velocypack/include/velocypack/Slice.h b/3rdParty/velocypack/include/velocypack/Slice.h index c6c697d28d..8d7cf1031d 100644 --- a/3rdParty/velocypack/include/velocypack/Slice.h +++ b/3rdParty/velocypack/include/velocypack/Slice.h @@ -379,6 +379,7 @@ class Slice { // find number of items if (h <= 0x05) { // No offset table or length, need to compute: + VELOCYPACK_ASSERT(h != 0x00 && h != 0x01); ValueLength firstSubOffset = findDataOffset(h); Slice first(_start + firstSubOffset); ValueLength s = first.byteSize(); @@ -848,9 +849,14 @@ class Slice { } ValueLength findDataOffset(uint8_t head) const noexcept { - // Must be called for a nonempty array or object at start(): - VELOCYPACK_ASSERT(head <= 0x12); + // Must be called for a non-empty array or object at start(): + VELOCYPACK_ASSERT(head != 0x01 && head != 0x0a && head <= 0x14); unsigned int fsm = SliceStaticData::FirstSubMap[head]; + if (fsm == 0) { + // need to calculate the offset by reading the dynamic length + VELOCYPACK_ASSERT(head == 0x13 || head == 0x14); + return 1 + readVariableValueLength(_start + 1); + } if (fsm <= 2 && _start[2] != 0) { return 2; } diff --git a/3rdParty/velocypack/src/Slice.cpp b/3rdParty/velocypack/src/Slice.cpp index 16f608ee18..298437ba67 100644 --- a/3rdParty/velocypack/src/Slice.cpp +++ b/3rdParty/velocypack/src/Slice.cpp @@ -340,7 +340,9 @@ unsigned int const SliceStaticData::FirstSubMap[32] = { 3, // 0x0f, object with unsorted index table 5, // 0x10, object with unsorted index table 9, // 0x11, object with unsorted index table - 9, // 0x12, object with unsorted index table + 9, // 0x12, object with unsorted index table, + 0, // 0x13, compact array, no index table - note: the offset is dynamic! + 0, // 0x14, compact object, no index table - note: the offset is dynamic! 0}; // creates a Slice from Json and adds it to a scope diff --git a/arangod/Transaction/Helpers.cpp b/arangod/Transaction/Helpers.cpp index b2a2463560..5010703aea 100644 --- a/arangod/Transaction/Helpers.cpp +++ b/arangod/Transaction/Helpers.cpp @@ -102,6 +102,10 @@ std::string transaction::helpers::extractIdString(CollectionNameResolver const* if (slice.isObject()) { // extract id attribute from object + if (slice.isEmptyObject()) { + THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID); + } + uint8_t const* p = slice.begin() + slice.findDataOffset(slice.head()); if (*p == basics::VelocyPackHelper::KeyAttribute) { // skip over attribute name @@ -115,7 +119,7 @@ std::string transaction::helpers::extractIdString(CollectionNameResolver const* if (id.isCustom()) { // we should be pointing to a custom value now TRI_ASSERT(id.head() == 0xf3); - + return makeIdFromCustom(resolver, id, key); } if (id.isString()) {