Index: Source/WebCore/Modules/indexeddb/IDBLevelDBCoding.cpp |
=================================================================== |
--- Source/WebCore/Modules/indexeddb/IDBLevelDBCoding.cpp (revision 144088) |
+++ Source/WebCore/Modules/indexeddb/IDBLevelDBCoding.cpp (working copy) |
@@ -335,17 +335,15 @@ |
ASSERT(limit >= p); |
int64_t len; |
p = decodeVarInt(p, limit, len); |
- if (!p) |
+ if (!p || len < 0 || p + len * 2 > limit) |
return 0; |
- if (p + len * 2 > limit) |
- return 0; |
foundString = decodeString(p, p + len * 2); |
p += len * 2; |
return p; |
} |
-int compareEncodedStringsWithLength(const char*& p, const char* limitP, const char*& q, const char* limitQ) |
+int compareEncodedStringsWithLength(const char*& p, const char* limitP, const char*& q, const char* limitQ, bool& ok) |
{ |
ASSERT(&p != &q); |
ASSERT(limitP >= p); |
@@ -353,6 +351,10 @@ |
int64_t lenP, lenQ; |
p = decodeVarInt(p, limitP, lenP); |
q = decodeVarInt(q, limitQ, lenQ); |
+ if (!p || !q || lenP < 0 || lenQ < 0) { |
+ ok = false; |
+ return 0; |
+ } |
ASSERT(p && q); |
ASSERT(lenP >= 0); |
ASSERT(lenQ >= 0); |
@@ -364,9 +366,12 @@ |
p += lenP * 2; |
q += lenQ * 2; |
- if (p > limitP || q > limitQ) |
+ if (p > limitP || q > limitQ) { |
+ ok = false; |
return 0; |
+ } |
+ ok = true; |
const size_t lmin = static_cast<size_t>(lenP < lenQ ? lenP : lenQ); |
if (int x = memcmp(startP, startQ, lmin * 2)) |
return x; |
@@ -462,10 +467,8 @@ |
case IDBKeyArrayTypeByte: { |
int64_t length; |
p = decodeVarInt(p, limit, length); |
- if (!p) |
+ if (!p || length < 0) |
return 0; |
- if (length < 0) |
- return 0; |
IDBKey::KeyArray array; |
while (length--) { |
RefPtr<IDBKey> key; |
@@ -522,10 +525,8 @@ |
case IDBKeyArrayTypeByte: { |
int64_t length; |
p = decodeVarInt(p, limit, length); |
- if (!p) |
+ if (!p || length < 0) |
return 0; |
- if (length < 0) |
- return 0; |
while (length--) { |
p = extractEncodedIDBKey(p, limit); |
if (!p) |
@@ -536,10 +537,8 @@ |
case IDBKeyStringTypeByte: { |
int64_t length; |
p = decodeVarInt(p, limit, length); |
- if (!p) |
+ if (!p || length < 0 || p + length * 2 > limit) |
return 0; |
- if (p + length * 2 > limit) |
- return 0; |
p += length * 2; |
break; |
} |
@@ -582,8 +581,9 @@ |
return IDBKey::InvalidType; |
} |
-int compareEncodedIDBKeys(const char*& ptrA, const char* limitA, const char*& ptrB, const char* limitB) |
+int compareEncodedIDBKeys(const char*& ptrA, const char* limitA, const char*& ptrB, const char* limitB, bool& ok) |
{ |
+ ok = true; |
ASSERT(&ptrA != &ptrB); |
ASSERT(ptrA < limitA); |
ASSERT(ptrB < limitB); |
@@ -601,16 +601,15 @@ |
case IDBKeyArrayTypeByte: { |
int64_t lengthA, lengthB; |
ptrA = decodeVarInt(ptrA, limitA, lengthA); |
- if (!ptrA) |
- return 0; |
ptrB = decodeVarInt(ptrB, limitB, lengthB); |
- if (!ptrB) |
+ if (!ptrA || !ptrB || lengthA < 0 || lengthB < 0) { |
+ ok = false; |
return 0; |
- if (lengthA < 0 || lengthB < 0) |
- return 0; |
+ } |
for (int64_t i = 0; i < lengthA && i < lengthB; ++i) { |
- if (int cmp = compareEncodedIDBKeys(ptrA, limitA, ptrB, limitB)) |
- return cmp; |
+ int result = compareEncodedIDBKeys(ptrA, limitA, ptrB, limitB, ok); |
+ if (!ok || result) |
+ return result; |
} |
if (lengthA < lengthB) |
return -1; |
@@ -619,14 +618,18 @@ |
return 0; |
} |
case IDBKeyStringTypeByte: |
- return compareEncodedStringsWithLength(ptrA, limitA, ptrB, limitB); |
+ return compareEncodedStringsWithLength(ptrA, limitA, ptrB, limitB, ok); |
case IDBKeyDateTypeByte: |
case IDBKeyNumberTypeByte: { |
double d, e; |
ptrA = decodeDouble(ptrA, limitA, &d); |
+ ptrB = decodeDouble(ptrB, limitB, &e); |
ASSERT(ptrA); |
- ptrB = decodeDouble(ptrB, limitB, &e); |
ASSERT(ptrB); |
+ if (!ptrA || !ptrB) { |
+ ok = false; |
+ return 0; |
+ } |
if (d < e) |
return -1; |
if (d > e) |
@@ -639,7 +642,7 @@ |
return 0; |
} |
-int compareEncodedIDBKeys(const Vector<char>& keyA, const Vector<char>& keyB) |
+int compareEncodedIDBKeys(const Vector<char>& keyA, const Vector<char>& keyB, bool& ok) |
{ |
ASSERT(keyA.size() >= 1); |
ASSERT(keyB.size() >= 1); |
@@ -649,7 +652,7 @@ |
const char* ptrB = keyB.data(); |
const char* limitB = ptrB + keyB.size(); |
- return compareEncodedIDBKeys(ptrA, limitA, ptrB, limitB); |
+ return compareEncodedIDBKeys(ptrA, limitA, ptrB, limitB, ok); |
} |
Vector<char> encodeIDBKeyPath(const IDBKeyPath& keyPath) |
@@ -723,21 +726,30 @@ |
namespace { |
template<typename KeyType> |
-int compare(const LevelDBSlice& a, const LevelDBSlice& b, bool ignoreDuplicates = false) |
+int compare(const LevelDBSlice& a, const LevelDBSlice& b, bool ignoreDuplicates, bool& ok) |
{ |
KeyType keyA; |
KeyType keyB; |
const char* ptrA = KeyType::decode(a.begin(), a.end(), &keyA); |
- ASSERT_UNUSED(ptrA, ptrA); |
+ ASSERT(ptrA); |
+ if (!ptrA) { |
+ ok = false; |
+ return 0; |
+ } |
const char* ptrB = KeyType::decode(b.begin(), b.end(), &keyB); |
- ASSERT_UNUSED(ptrB, ptrB); |
+ ASSERT(ptrB); |
+ if (!ptrB) { |
+ ok = false; |
+ return 0; |
+ } |
+ ok = true; |
return keyA.compare(keyB); |
} |
template<> |
-int compare<ExistsEntryKey>(const LevelDBSlice& a, const LevelDBSlice& b, bool ignoreDuplicates) |
+int compare<ExistsEntryKey>(const LevelDBSlice& a, const LevelDBSlice& b, bool ignoreDuplicates, bool& ok) |
{ |
KeyPrefix prefixA; |
KeyPrefix prefixB; |
@@ -756,11 +768,11 @@ |
// Prefixes are not compared - it is assumed this was already done. |
ASSERT(!prefixA.compare(prefixB)); |
- return compareEncodedIDBKeys(ptrA, a.end(), ptrB, b.end()); |
+ return compareEncodedIDBKeys(ptrA, a.end(), ptrB, b.end(), ok); |
} |
template<> |
-int compare<ObjectStoreDataKey>(const LevelDBSlice& a, const LevelDBSlice& b, bool ignoreDuplicates) |
+int compare<ObjectStoreDataKey>(const LevelDBSlice& a, const LevelDBSlice& b, bool ignoreDuplicates, bool& ok) |
{ |
KeyPrefix prefixA; |
KeyPrefix prefixB; |
@@ -779,11 +791,11 @@ |
// Prefixes are not compared - it is assumed this was already done. |
ASSERT(!prefixA.compare(prefixB)); |
- return compareEncodedIDBKeys(ptrA, a.end(), ptrB, b.end()); |
+ return compareEncodedIDBKeys(ptrA, a.end(), ptrB, b.end(), ok); |
} |
template<> |
-int compare<IndexDataKey>(const LevelDBSlice& a, const LevelDBSlice& b, bool ignoreDuplicates) |
+int compare<IndexDataKey>(const LevelDBSlice& a, const LevelDBSlice& b, bool ignoreDuplicates, bool& ok) |
{ |
KeyPrefix prefixA; |
KeyPrefix prefixB; |
@@ -803,8 +815,9 @@ |
ASSERT(!prefixA.compare(prefixB)); |
// index key |
- if (int x = compareEncodedIDBKeys(ptrA, a.end(), ptrB, b.end())) |
- return x; |
+ int result = compareEncodedIDBKeys(ptrA, a.end(), ptrB, b.end(), ok); |
+ if (!ok || result) |
+ return result; |
if (ignoreDuplicates) |
return 0; |
@@ -816,7 +829,7 @@ |
if (ptrB != b.end()) |
ptrB = decodeVarInt(ptrB, b.end(), sequenceNumberB); |
- // primar key [optional] |
+ // primary key [optional] |
if (!ptrA || !ptrB) |
return 0; |
if (ptrA == a.end() && ptrB == b.end()) |
@@ -826,15 +839,14 @@ |
if (ptrB == b.end()) |
return 1; |
- if (int x = compareEncodedIDBKeys(ptrA, a.end(), ptrB, b.end())) |
- return x; |
+ result = compareEncodedIDBKeys(ptrA, a.end(), ptrB, b.end(), ok); |
+ if (!ok || result) |
+ return result; |
return compareInts(sequenceNumberA, sequenceNumberB); |
} |
-} |
- |
-int compare(const LevelDBSlice& a, const LevelDBSlice& b, bool indexKeys) |
+int compare(const LevelDBSlice& a, const LevelDBSlice& b, bool indexKeys, bool& ok) |
{ |
const char* ptrA = a.begin(); |
const char* ptrB = b.begin(); |
@@ -848,7 +860,12 @@ |
ptrB = KeyPrefix::decode(ptrB, endB, &prefixB); |
ASSERT(ptrA); |
ASSERT(ptrB); |
+ if (!ptrA || !ptrB) { |
+ ok = false; |
+ return 0; |
+ } |
+ ok = true; |
if (int x = prefixA.compare(prefixB)) |
return x; |
@@ -864,10 +881,11 @@ |
if (typeByteA < MaxSimpleGlobalMetaDataTypeByte) |
return 0; |
+ const bool ignoreDuplicates = false; |
if (typeByteA == DatabaseFreeListTypeByte) |
- return compare<DatabaseFreeListKey>(a, b); |
+ return compare<DatabaseFreeListKey>(a, b, ignoreDuplicates, ok); |
if (typeByteA == DatabaseNameTypeByte) |
- return compare<DatabaseNameKey>(a, b); |
+ return compare<DatabaseNameKey>(a, b, ignoreDuplicates, ok); |
} |
if (prefixA.type() == KeyPrefix::DatabaseMetaData) { |
@@ -882,18 +900,19 @@ |
if (typeByteA < DatabaseMetaDataKey::MaxSimpleMetaDataType) |
return 0; |
+ const bool ignoreDuplicates = false; |
if (typeByteA == ObjectStoreMetaDataTypeByte) |
- return compare<ObjectStoreMetaDataKey>(a, b); |
+ return compare<ObjectStoreMetaDataKey>(a, b, ignoreDuplicates, ok); |
if (typeByteA == IndexMetaDataTypeByte) |
- return compare<IndexMetaDataKey>(a, b); |
+ return compare<IndexMetaDataKey>(a, b, ignoreDuplicates, ok); |
if (typeByteA == ObjectStoreFreeListTypeByte) |
- return compare<ObjectStoreFreeListKey>(a, b); |
+ return compare<ObjectStoreFreeListKey>(a, b, ignoreDuplicates, ok); |
if (typeByteA == IndexFreeListTypeByte) |
- return compare<IndexFreeListKey>(a, b); |
+ return compare<IndexFreeListKey>(a, b, ignoreDuplicates, ok); |
if (typeByteA == ObjectStoreNamesTypeByte) |
- return compare<ObjectStoreNamesKey>(a, b); |
+ return compare<ObjectStoreNamesKey>(a, b, ignoreDuplicates, ok); |
if (typeByteA == IndexNamesKeyTypeByte) |
- return compare<IndexNamesKey>(a, b); |
+ return compare<IndexNamesKey>(a, b, ignoreDuplicates, ok); |
} |
if (prefixA.type() == KeyPrefix::ObjectStoreData) { |
@@ -904,7 +923,8 @@ |
if (ptrB == endB) |
return 1; // FIXME: This case of non-existing user keys should not have to be handled this way. |
- return compare<ObjectStoreDataKey>(a, b); |
+ const bool ignoreDuplicates = false; |
+ return compare<ObjectStoreDataKey>(a, b, ignoreDuplicates, ok); |
} |
if (prefixA.type() == KeyPrefix::ExistsEntry) { |
if (ptrA == endA && ptrB == endB) |
@@ -914,7 +934,8 @@ |
if (ptrB == endB) |
return 1; // FIXME: This case of non-existing user keys should not have to be handled this way. |
- return compare<ExistsEntryKey>(a, b); |
+ const bool ignoreDuplicates = false; |
+ return compare<ExistsEntryKey>(a, b, ignoreDuplicates, ok); |
} |
if (prefixA.type() == KeyPrefix::IndexData) { |
if (ptrA == endA && ptrB == endB) |
@@ -925,14 +946,26 @@ |
return 1; // FIXME: This case of non-existing user keys should not have to be handled this way. |
bool ignoreDuplicates = indexKeys; |
- return compare<IndexDataKey>(a, b, ignoreDuplicates); |
+ return compare<IndexDataKey>(a, b, ignoreDuplicates, ok); |
} |
ASSERT_NOT_REACHED(); |
+ ok = false; |
return 0; |
} |
+} |
+int compare(const LevelDBSlice& a, const LevelDBSlice& b, bool indexKeys) |
+{ |
+ bool ok; |
+ int result = compare(a, b, indexKeys, ok); |
+ ASSERT(ok); |
+ if (!ok) |
+ return 0; |
+ return result; |
+} |
+ |
KeyPrefix::KeyPrefix() |
: m_databaseId(InvalidType) |
, m_objectStoreId(InvalidType) |
@@ -1538,9 +1571,9 @@ |
return encode(databaseId, objectStoreId, encodeIDBKey(userKey)); |
} |
-int ObjectStoreDataKey::compare(const ObjectStoreDataKey& other) |
+int ObjectStoreDataKey::compare(const ObjectStoreDataKey& other, bool& ok) |
{ |
- return compareEncodedIDBKeys(m_encodedUserKey, other.m_encodedUserKey); |
+ return compareEncodedIDBKeys(m_encodedUserKey, other.m_encodedUserKey, ok); |
} |
PassRefPtr<IDBKey> ObjectStoreDataKey::userKey() const |
@@ -1579,9 +1612,9 @@ |
return encode(databaseId, objectStoreId, encodeIDBKey(userKey)); |
} |
-int ExistsEntryKey::compare(const ExistsEntryKey& other) |
+int ExistsEntryKey::compare(const ExistsEntryKey& other, bool& ok) |
{ |
- return compareEncodedIDBKeys(m_encodedUserKey, other.m_encodedUserKey); |
+ return compareEncodedIDBKeys(m_encodedUserKey, other.m_encodedUserKey, ok); |
} |
PassRefPtr<IDBKey> ExistsEntryKey::userKey() const |
@@ -1662,17 +1695,19 @@ |
return encode(databaseId, objectStoreId, indexId, maxIDBKey(), maxIDBKey(), INT64_MAX); |
} |
-int IndexDataKey::compare(const IndexDataKey& other, bool ignoreDuplicates) |
+int IndexDataKey::compare(const IndexDataKey& other, bool ignoreDuplicates, bool& ok) |
{ |
ASSERT(m_databaseId >= 0); |
ASSERT(m_objectStoreId >= 0); |
ASSERT(m_indexId >= 0); |
- if (int x = compareEncodedIDBKeys(m_encodedUserKey, other.m_encodedUserKey)) |
- return x; |
+ int result = compareEncodedIDBKeys(m_encodedUserKey, other.m_encodedUserKey, ok); |
+ if (!ok || result) |
+ return result; |
if (ignoreDuplicates) |
return 0; |
- if (int x = compareEncodedIDBKeys(m_encodedPrimaryKey, other.m_encodedPrimaryKey)) |
- return x; |
+ result = compareEncodedIDBKeys(m_encodedPrimaryKey, other.m_encodedPrimaryKey, ok); |
+ if (!ok || result) |
+ return result; |
return compareInts(m_sequenceNumber, other.m_sequenceNumber); |
} |