0

indexeddb: add recursion limit for idb key decoding

Bug: 1114430
Change-Id: I8379fe033e39ffc898e8799cd3c1e1e8e1743984
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2393188
Commit-Queue: enne <enne@chromium.org>
Commit-Queue: Jeremy Roman <jbroman@chromium.org>
Auto-Submit: enne <enne@chromium.org>
Reviewed-by: Jeremy Roman <jbroman@chromium.org>
Reviewed-by: Daniel Murphy <dmurph@chromium.org>
Cr-Commit-Position: refs/heads/master@{#805089}
This commit is contained in:
Adrienne Walker
2020-09-08 21:32:46 +00:00
committed by Commit Bot
parent 73f1a5ff4c
commit d46483a800
3 changed files with 20 additions and 10 deletions
content/browser/indexed_db
third_party/blink
public
common
renderer
bindings

@ -359,10 +359,15 @@ bool DecodeBinary(StringPiece* slice, base::span<const uint8_t>* value) {
return true;
}
bool DecodeIDBKey(StringPiece* slice, std::unique_ptr<IndexedDBKey>* value) {
bool DecodeIDBKeyRecursive(StringPiece* slice,
std::unique_ptr<IndexedDBKey>* value,
size_t recursion) {
if (slice->empty())
return false;
if (recursion > IndexedDBKey::kMaximumDepth)
return false;
unsigned char type = (*slice)[0];
slice->remove_prefix(1);
@ -378,7 +383,7 @@ bool DecodeIDBKey(StringPiece* slice, std::unique_ptr<IndexedDBKey>* value) {
IndexedDBKey::KeyArray array;
while (length--) {
std::unique_ptr<IndexedDBKey> key;
if (!DecodeIDBKey(slice, &key))
if (!DecodeIDBKeyRecursive(slice, &key, recursion + 1))
return false;
array.push_back(*key);
}
@ -425,6 +430,10 @@ bool DecodeIDBKey(StringPiece* slice, std::unique_ptr<IndexedDBKey>* value) {
return false;
}
bool DecodeIDBKey(StringPiece* slice, std::unique_ptr<IndexedDBKey>* value) {
return DecodeIDBKeyRecursive(slice, value, 0);
}
bool DecodeDouble(StringPiece* slice, double* value) {
if (slice->size() < sizeof(*value))
return false;

@ -21,6 +21,11 @@ class BLINK_COMMON_EXPORT IndexedDBKey {
public:
typedef std::vector<IndexedDBKey> KeyArray;
// Non-standard limits, selected to avoid breaking real-world use of the API
// while also preventing buggy (or malicious) code from causing crashes.
static constexpr size_t kMaximumDepth = 2000;
static constexpr size_t kMaximumArraySize = 1000000;
IndexedDBKey(); // Defaults to mojom::IDBKeyType::Invalid.
explicit IndexedDBKey(mojom::IDBKeyType); // must be Null or Invalid
explicit IndexedDBKey(KeyArray array);

@ -25,6 +25,7 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.h"
#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_factory.h"
@ -167,11 +168,6 @@ v8::Local<v8::Value> ToV8(const IDBAny* impl,
return v8::Undefined(isolate);
}
// Non-standard limits, selected to avoid breaking real-world use of the API
// while also preventing buggy (or malicious) code from causing crashes.
const size_t kMaximumDepth = 2000;
const size_t kMaximumArraySize = 1000000;
// Convert a simple (non-Array) script value to an Indexed DB key. If the
// conversion fails due to a detached buffer, an exception is thrown. If
// the value can't be converted into a key, an 'Invalid' key is returned. This
@ -264,7 +260,7 @@ static std::unique_ptr<IDBKey> CreateIDBKeyFromValue(
// Initial state.
{
v8::Local<v8::Array> array = value.As<v8::Array>();
if (array->Length() > kMaximumArraySize)
if (array->Length() > IndexedDBKey::kMaximumArraySize)
return IDBKey::CreateInvalid();
stack.push_back(std::make_unique<Record>(array));
@ -320,8 +316,8 @@ static std::unique_ptr<IDBKey> CreateIDBKeyFromValue(
} else {
// A sub-array; push onto the stack and start processing it.
v8::Local<v8::Array> array = item.As<v8::Array>();
if (seen.Contains(array) || stack.size() >= kMaximumDepth ||
array->Length() > kMaximumArraySize) {
if (seen.Contains(array) || stack.size() >= IndexedDBKey::kMaximumDepth ||
array->Length() > IndexedDBKey::kMaximumArraySize) {
return IDBKey::CreateInvalid();
}