Changeset 145435 in webkit
- Timestamp:
- Mar 11, 2013 4:57:21 PM (11 years ago)
- Location:
- trunk/Source
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r145433 r145435 1 2013-03-11 Alec Flett <alecflett@chromium.org> 2 3 IndexedDB: Protect against key prefix overflows 4 https://bugs.webkit.org/show_bug.cgi?id=111138 5 6 Reviewed by Tony Chang. 7 8 This reworks the boundary checking for all databaseId, 9 objectStoreId, and indexId, including negative and 10 zero-based ids. All entrypoints into IDBLevelDBCoding 11 are protected with explicit checks and all internal 12 uses of KeyPrefix are protected with ASSERTs in the 13 various constructors. 14 15 Tests: WebKit unit tests IDBBackingStoreTest.cpp in WebKit/chromium 16 17 * Modules/indexeddb/IDBBackingStore.h: Make all public methods boolean-based for errors. 18 * Modules/indexeddb/IDBLevelDBCoding.h: Add methods for checking databaseId, objectStoreId, and indexId. 19 1 20 2013-03-11 Philip Rogers <pdr@google.com> 2 21 -
trunk/Source/WebCore/Modules/indexeddb/IDBBackingStore.cpp
r145385 r145435 637 637 638 638 // FIXME: This should do some error handling rather than plowing ahead when bad data is encountered. 639 voidIDBBackingStore::getObjectStores(int64_t databaseId, IDBDatabaseMetadata::ObjectStoreMap* objectStores)639 bool IDBBackingStore::getObjectStores(int64_t databaseId, IDBDatabaseMetadata::ObjectStoreMap* objectStores) 640 640 { 641 641 IDB_TRACE("IDBBackingStore::getObjectStores"); 642 if (!KeyPrefix::isValidDatabaseId(databaseId)) 643 return false; 642 644 const Vector<char> startKey = ObjectStoreMetaDataKey::encode(databaseId, 1, 0); 643 645 const Vector<char> stopKey = ObjectStoreMetaDataKey::encodeMaxKey(databaseId); … … 725 727 726 728 IDBObjectStoreMetadata metadata(objectStoreName, objectStoreId, keyPath, autoIncrement, maxIndexId); 727 getIndexes(databaseId, objectStoreId, &metadata.indexes); 729 if (!getIndexes(databaseId, objectStoreId, &metadata.indexes)) 730 return false; 728 731 objectStores->set(objectStoreId, metadata); 729 732 } 733 return true; 730 734 } 731 735 … … 751 755 { 752 756 IDB_TRACE("IDBBackingStore::createObjectStore"); 757 if (!KeyPrefix::validIds(databaseId, objectStoreId)) 758 return false; 753 759 LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction); 754 760 if (!setMaxObjectStoreId(levelDBTransaction, databaseId, objectStoreId)) … … 780 786 { 781 787 IDB_TRACE("IDBBackingStore::deleteObjectStore"); 788 if (!KeyPrefix::validIds(databaseId, objectStoreId)) 789 return false; 782 790 LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction); 783 791 … … 801 809 deleteRange(levelDBTransaction, IndexMetaDataKey::encode(databaseId, objectStoreId, 0, 0), IndexMetaDataKey::encodeMaxKey(databaseId, objectStoreId)); 802 810 803 clearObjectStore(transaction, databaseId, objectStoreId); 804 return true; 811 return clearObjectStore(transaction, databaseId, objectStoreId); 805 812 } 806 813 … … 808 815 { 809 816 IDB_TRACE("IDBBackingStore::getRecord"); 817 if (!KeyPrefix::validIds(databaseId, objectStoreId)) 818 return false; 810 819 LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction); 811 820 … … 864 873 { 865 874 IDB_TRACE("IDBBackingStore::putRecord"); 875 if (!KeyPrefix::validIds(databaseId, objectStoreId)) 876 return false; 866 877 ASSERT(key.isValid()); 878 867 879 LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction); 868 880 int64_t version = -1; … … 888 900 } 889 901 890 voidIDBBackingStore::clearObjectStore(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId)902 bool IDBBackingStore::clearObjectStore(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId) 891 903 { 892 904 IDB_TRACE("IDBBackingStore::clearObjectStore"); 905 if (!KeyPrefix::validIds(databaseId, objectStoreId)) 906 return false; 893 907 LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction); 894 const Vector<char> startKey = KeyPrefix(databaseId, objectStoreId , 0).encode();895 const Vector<char> stopKey = KeyPrefix(databaseId, objectStoreId + 1 , 0).encode();908 const Vector<char> startKey = KeyPrefix(databaseId, objectStoreId).encode(); 909 const Vector<char> stopKey = KeyPrefix(databaseId, objectStoreId + 1).encode(); 896 910 897 911 deleteRange(levelDBTransaction, startKey, stopKey); 898 } 899 900 void IDBBackingStore::deleteRecord(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId, const RecordIdentifier& recordIdentifier) 912 return true; 913 } 914 915 bool IDBBackingStore::deleteRecord(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId, const RecordIdentifier& recordIdentifier) 901 916 { 902 917 IDB_TRACE("IDBBackingStore::deleteRecord"); 918 if (!KeyPrefix::validIds(databaseId, objectStoreId)) 919 return false; 903 920 LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction); 904 921 … … 908 925 const Vector<char> existsEntryKey = ExistsEntryKey::encode(databaseId, objectStoreId, recordIdentifier.primaryKey()); 909 926 levelDBTransaction->remove(existsEntryKey); 927 return true; 910 928 } 911 929 … … 913 931 bool IDBBackingStore::getKeyGeneratorCurrentNumber(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t& keyGeneratorCurrentNumber) 914 932 { 933 if (!KeyPrefix::validIds(databaseId, objectStoreId)) 934 return false; 915 935 LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction); 916 936 … … 961 981 bool IDBBackingStore::maybeUpdateKeyGeneratorCurrentNumber(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t newNumber, bool checkCurrent) 962 982 { 983 if (!KeyPrefix::validIds(databaseId, objectStoreId)) 984 return false; 963 985 LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction); 964 986 … … 980 1002 { 981 1003 IDB_TRACE("IDBBackingStore::keyExistsInObjectStore"); 1004 if (!KeyPrefix::validIds(databaseId, objectStoreId)) 1005 return false; 982 1006 found = false; 983 1007 LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction); … … 1018 1042 1019 1043 // FIXME: This should do some error handling rather than plowing ahead when bad data is encountered. 1020 voidIDBBackingStore::getIndexes(int64_t databaseId, int64_t objectStoreId, IDBObjectStoreMetadata::IndexMap* indexes)1044 bool IDBBackingStore::getIndexes(int64_t databaseId, int64_t objectStoreId, IDBObjectStoreMetadata::IndexMap* indexes) 1021 1045 { 1022 1046 IDB_TRACE("IDBBackingStore::getIndexes"); 1047 if (!KeyPrefix::validIds(databaseId, objectStoreId)) 1048 return false; 1023 1049 const Vector<char> startKey = IndexMetaDataKey::encode(databaseId, objectStoreId, 0, 0); 1024 1050 const Vector<char> stopKey = IndexMetaDataKey::encode(databaseId, objectStoreId + 1, 0, 0); … … 1069 1095 indexes->set(indexId, IDBIndexMetadata(indexName, indexId, keyPath, indexUnique, indexMultiEntry)); 1070 1096 } 1097 return true; 1071 1098 } 1072 1099 … … 1096 1123 { 1097 1124 IDB_TRACE("IDBBackingStore::createIndex"); 1125 if (!KeyPrefix::validIds(databaseId, objectStoreId, indexId)) 1126 return false; 1098 1127 LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction); 1099 1128 if (!setMaxIndexId(levelDBTransaction, databaseId, objectStoreId, indexId)) … … 1112 1141 } 1113 1142 1114 voidIDBBackingStore::deleteIndex(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId)1143 bool IDBBackingStore::deleteIndex(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId) 1115 1144 { 1116 1145 IDB_TRACE("IDBBackingStore::deleteIndex"); 1146 if (!KeyPrefix::validIds(databaseId, objectStoreId, indexId)) 1147 return false; 1117 1148 LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction); 1118 1149 … … 1124 1155 const Vector<char> indexDataEnd = IndexDataKey::encodeMaxKey(databaseId, objectStoreId, indexId); 1125 1156 deleteRange(levelDBTransaction, indexDataStart, indexDataEnd); 1126 } 1127 1128 void IDBBackingStore::putIndexDataForRecord(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& key, const RecordIdentifier& recordIdentifier) 1157 return true; 1158 } 1159 1160 bool IDBBackingStore::putIndexDataForRecord(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& key, const RecordIdentifier& recordIdentifier) 1129 1161 { 1130 1162 IDB_TRACE("IDBBackingStore::putIndexDataForRecord"); 1131 1163 ASSERT(key.isValid()); 1132 ASSERT(indexId >= MinimumIndexId); 1164 if (!KeyPrefix::validIds(databaseId, objectStoreId, indexId)) 1165 return false; 1133 1166 1134 1167 LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction); … … 1140 1173 1141 1174 levelDBTransaction->put(indexDataKey, data); 1175 return true; 1142 1176 } 1143 1177 … … 1190 1224 { 1191 1225 IDB_TRACE("IDBBackingStore::findKeyInIndex"); 1226 ASSERT(KeyPrefix::validIds(databaseId, objectStoreId, indexId)); 1227 1192 1228 ASSERT(foundEncodedPrimaryKey.isEmpty()); 1193 1229 found = false; … … 1230 1266 { 1231 1267 IDB_TRACE("IDBBackingStore::getPrimaryKeyViaIndex"); 1268 if (!KeyPrefix::validIds(databaseId, objectStoreId, indexId)) 1269 return false; 1232 1270 1233 1271 bool found = false; … … 1249 1287 { 1250 1288 IDB_TRACE("IDBBackingStore::keyExistsInIndex"); 1289 if (!KeyPrefix::validIds(databaseId, objectStoreId, indexId)) 1290 return false; 1251 1291 1252 1292 exists = false; … … 1763 1803 { 1764 1804 ASSERT(transaction); 1805 if (!KeyPrefix::validIds(databaseId, objectStoreId, indexId)) 1806 return false; 1807 1765 1808 bool lowerBound = range && range->lower(); 1766 1809 bool upperBound = range && range->upper(); -
trunk/Source/WebCore/Modules/indexeddb/IDBBackingStore.h
r145385 r145435 69 69 virtual bool deleteDatabase(const String& name); 70 70 71 void getObjectStores(int64_t databaseId, IDBDatabaseMetadata::ObjectStoreMap*);71 bool getObjectStores(int64_t databaseId, IDBDatabaseMetadata::ObjectStoreMap*) WARN_UNUSED_RETURN; 72 72 virtual bool createObjectStore(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, const String& name, const IDBKeyPath&, bool autoIncrement); 73 73 virtual bool deleteObjectStore(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId) WARN_UNUSED_RETURN; … … 90 90 virtual bool getRecord(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, const IDBKey&, Vector<char>& record) WARN_UNUSED_RETURN; 91 91 virtual bool putRecord(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, const IDBKey&, PassRefPtr<SharedBuffer> value, RecordIdentifier*) WARN_UNUSED_RETURN; 92 virtual void clearObjectStore(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId);93 virtual void deleteRecord(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, const RecordIdentifier&);92 virtual bool clearObjectStore(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId) WARN_UNUSED_RETURN; 93 virtual bool deleteRecord(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, const RecordIdentifier&) WARN_UNUSED_RETURN; 94 94 virtual bool getKeyGeneratorCurrentNumber(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, int64_t& currentNumber) WARN_UNUSED_RETURN; 95 95 virtual bool maybeUpdateKeyGeneratorCurrentNumber(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, int64_t newState, bool checkCurrent) WARN_UNUSED_RETURN; 96 96 virtual bool keyExistsInObjectStore(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, const IDBKey&, RecordIdentifier* foundRecordIdentifier, bool& found) WARN_UNUSED_RETURN; 97 97 98 virtual bool createIndex(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const String& name, const IDBKeyPath&, bool isUnique, bool isMultiEntry) ;99 virtual void deleteIndex(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, int64_t indexId);100 virtual void putIndexDataForRecord(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey&, const RecordIdentifier&);98 virtual bool createIndex(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const String& name, const IDBKeyPath&, bool isUnique, bool isMultiEntry) WARN_UNUSED_RETURN; 99 virtual bool deleteIndex(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, int64_t indexId) WARN_UNUSED_RETURN; 100 virtual bool putIndexDataForRecord(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey&, const RecordIdentifier&) WARN_UNUSED_RETURN; 101 101 virtual bool getPrimaryKeyViaIndex(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey&, RefPtr<IDBKey>& primaryKey) WARN_UNUSED_RETURN; 102 102 virtual bool keyExistsInIndex(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& indexKey, RefPtr<IDBKey>& foundPrimaryKey, bool& exists) WARN_UNUSED_RETURN; … … 179 179 private: 180 180 bool findKeyInIndex(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey&, Vector<char>& foundEncodedPrimaryKey, bool& found); 181 void getIndexes(int64_t databaseId, int64_t objectStoreId, IDBObjectStoreMetadata::IndexMap*);181 bool getIndexes(int64_t databaseId, int64_t objectStoreId, IDBObjectStoreMetadata::IndexMap*) WARN_UNUSED_RETURN; 182 182 183 183 String m_identifier; -
trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.cpp
r145385 r145435 180 180 class DeleteIndexOperation : public IDBTransactionBackendImpl::Operation { 181 181 public: 182 static PassOwnPtr<IDBTransactionBackendImpl::Operation> create(PassRefPtr<IDBBackingStore> backingStore, int64_t objectStoreId, int64_t indexId)183 { 184 return adoptPtr(new DeleteIndexOperation(backingStore, objectStoreId, index Id));185 } 186 virtual void perform(IDBTransactionBackendImpl*); 187 private: 188 DeleteIndexOperation(PassRefPtr<IDBBackingStore> backingStore, int64_t objectStoreId, int64_t indexId)182 static PassOwnPtr<IDBTransactionBackendImpl::Operation> create(PassRefPtr<IDBBackingStore> backingStore, int64_t objectStoreId, const IDBIndexMetadata& indexMetadata) 183 { 184 return adoptPtr(new DeleteIndexOperation(backingStore, objectStoreId, indexMetadata)); 185 } 186 virtual void perform(IDBTransactionBackendImpl*); 187 private: 188 DeleteIndexOperation(PassRefPtr<IDBBackingStore> backingStore, int64_t objectStoreId, const IDBIndexMetadata& indexMetadata) 189 189 : m_backingStore(backingStore) 190 190 , m_objectStoreId(objectStoreId) 191 , m_index Id(indexId)191 , m_indexMetadata(indexMetadata) 192 192 { 193 193 } … … 195 195 const RefPtr<IDBBackingStore> m_backingStore; 196 196 const int64_t m_objectStoreId; 197 const int64_t m_indexId;197 const IDBIndexMetadata m_indexMetadata; 198 198 }; 199 199 … … 535 535 if (!ok) 536 536 return false; 537 if (success) { 538 m_backingStore->getObjectStores(m_metadata.id, &m_metadata.objectStores); 539 return true; 540 } 537 if (success) 538 return m_backingStore->getObjectStores(m_metadata.id, &m_metadata.objectStores); 539 541 540 return m_backingStore->createIDBDatabaseMetaData(m_metadata.name, m_metadata.version, m_metadata.intVersion, m_metadata.id); 542 541 } … … 641 640 const IDBIndexMetadata& indexMetadata = objectStore.indexes.get(indexId); 642 641 643 transaction->scheduleTask(DeleteIndexOperation::create(m_backingStore, objectStoreId, index Id), DeleteIndexAbortOperation::create(this, objectStoreId, indexMetadata));642 transaction->scheduleTask(DeleteIndexOperation::create(m_backingStore, objectStoreId, indexMetadata), DeleteIndexAbortOperation::create(this, objectStoreId, indexMetadata)); 644 643 645 644 removeIndex(objectStoreId, indexId); … … 649 648 { 650 649 IDB_TRACE("DeleteIndexOperation"); 651 m_backingStore->deleteIndex(transaction->backingStoreTransaction(), transaction->database()->id(), m_objectStoreId, m_indexId); 650 bool ok = m_backingStore->deleteIndex(transaction->backingStoreTransaction(), transaction->database()->id(), m_objectStoreId, m_indexMetadata.id); 651 if (!ok) { 652 RefPtr<IDBDatabaseError> error = IDBDatabaseError::create(IDBDatabaseException::UnknownError, String::format("Internal error deleting index '%s'.", m_indexMetadata.name.utf8().data())); 653 transaction->abort(error); 654 } 652 655 } 653 656 … … 1024 1027 if (backingStoreCursor) { 1025 1028 do { 1026 m_backingStore->deleteRecord(transaction->backingStoreTransaction(), m_databaseId, m_objectStoreId, backingStoreCursor->recordIdentifier()); 1029 if (!m_backingStore->deleteRecord(transaction->backingStoreTransaction(), m_databaseId, m_objectStoreId, backingStoreCursor->recordIdentifier())) { 1030 m_callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Error deleting data in range")); 1031 return; 1032 } 1027 1033 } while (backingStoreCursor->continueFunction(0)); 1028 1034 } … … 1045 1051 { 1046 1052 IDB_TRACE("ObjectStoreClearOperation"); 1047 m_backingStore->clearObjectStore(transaction->backingStoreTransaction(), m_databaseId, m_objectStoreId); 1053 if (!m_backingStore->clearObjectStore(transaction->backingStoreTransaction(), m_databaseId, m_objectStoreId)) { 1054 m_callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Error clearing object store")); 1055 return; 1056 } 1048 1057 m_callbacks->onSuccess(); 1049 1058 } -
trunk/Source/WebCore/Modules/indexeddb/IDBLevelDBCoding.cpp
r145385 r145435 974 974 } 975 975 976 KeyPrefix::KeyPrefix(int64_t databaseId) 977 : m_databaseId(databaseId) 978 , m_objectStoreId(0) 979 , m_indexId(0) 980 { 981 ASSERT(KeyPrefix::isValidDatabaseId(databaseId)); 982 } 983 984 KeyPrefix::KeyPrefix(int64_t databaseId, int64_t objectStoreId) 985 : m_databaseId(databaseId) 986 , m_objectStoreId(objectStoreId) 987 , m_indexId(0) 988 { 989 ASSERT(KeyPrefix::isValidDatabaseId(databaseId)); 990 ASSERT(KeyPrefix::isValidObjectStoreId(objectStoreId)); 991 } 992 976 993 KeyPrefix::KeyPrefix(int64_t databaseId, int64_t objectStoreId, int64_t indexId) 977 994 : m_databaseId(databaseId) … … 979 996 , m_indexId(indexId) 980 997 { 998 ASSERT(KeyPrefix::isValidDatabaseId(databaseId)); 999 ASSERT(KeyPrefix::isValidObjectStoreId(objectStoreId)); 1000 ASSERT(KeyPrefix::isValidIndexId(indexId)); 1001 } 1002 1003 KeyPrefix::KeyPrefix(Type type, int64_t databaseId, int64_t objectStoreId, int64_t indexId) 1004 : m_databaseId(databaseId) 1005 , m_objectStoreId(objectStoreId) 1006 , m_indexId(indexId) 1007 { 1008 ASSERT(type == InvalidType); 1009 ASSERT(KeyPrefix::isValidDatabaseId(databaseId)); 1010 ASSERT(KeyPrefix::isValidObjectStoreId(objectStoreId)); 1011 } 1012 1013 1014 KeyPrefix KeyPrefix::createWithSpecialIndex(int64_t databaseId, int64_t objectStoreId, int64_t indexId) 1015 { 1016 ASSERT(KeyPrefix::isValidDatabaseId(databaseId)); 1017 ASSERT(KeyPrefix::isValidObjectStoreId(objectStoreId)); 1018 ASSERT(indexId); 1019 return KeyPrefix(InvalidType, databaseId, objectStoreId, indexId); 1020 } 1021 1022 1023 bool KeyPrefix::isValidDatabaseId(int64_t databaseId) 1024 { 1025 return (databaseId > 0) && (databaseId < KeyPrefix::kMaxDatabaseId); 1026 } 1027 1028 bool KeyPrefix::isValidObjectStoreId(int64_t objectStoreId) 1029 { 1030 return (objectStoreId > 0) && (objectStoreId < KeyPrefix::kMaxObjectStoreId); 1031 } 1032 1033 bool KeyPrefix::isValidIndexId(int64_t indexId) 1034 { 1035 return (indexId >= MinimumIndexId) && (indexId < KeyPrefix::kMaxIndexId); 981 1036 } 982 1037 … … 1005 1060 } 1006 1061 1062 Vector<char> KeyPrefix::encodeEmpty() 1063 { 1064 const Vector<char, 4> result(4, 0); 1065 ASSERT(encodeInternal(0, 0, 0) == Vector<char>(4, 0)); 1066 return result; 1067 } 1068 1007 1069 Vector<char> KeyPrefix::encode() const 1008 1070 { … … 1010 1072 ASSERT(m_objectStoreId != InvalidId); 1011 1073 ASSERT(m_indexId != InvalidId); 1012 1013 Vector<char> databaseIdString = encodeInt(m_databaseId); 1014 Vector<char> objectStoreIdString = encodeInt(m_objectStoreId); 1015 Vector<char> indexIdString = encodeInt(m_indexId); 1016 1017 ASSERT(databaseIdString.size() <= 8); 1018 ASSERT(objectStoreIdString.size() <= 8); 1019 ASSERT(indexIdString.size() <= 4); 1020 1021 1022 unsigned char firstByte = (databaseIdString.size() - 1) << 5 | (objectStoreIdString.size() - 1) << 2 | (indexIdString.size() - 1); 1074 return encodeInternal(m_databaseId, m_objectStoreId, m_indexId); 1075 } 1076 1077 Vector<char> KeyPrefix::encodeInternal(int64_t databaseId, int64_t objectStoreId, int64_t indexId) 1078 { 1079 Vector<char> databaseIdString = encodeIntSafely(databaseId, kMaxDatabaseId); 1080 Vector<char> objectStoreIdString = encodeIntSafely(objectStoreId, kMaxObjectStoreId); 1081 Vector<char> indexIdString = encodeIntSafely(indexId, kMaxIndexId); 1082 1083 ASSERT(databaseIdString.size() <= kMaxDatabaseIdSizeBytes); 1084 ASSERT(objectStoreIdString.size() <= kMaxObjectStoreIdSizeBytes); 1085 ASSERT(indexIdString.size() <= kMaxIndexIdSizeBytes); 1086 1087 unsigned char firstByte = (databaseIdString.size() - 1) << (kMaxObjectStoreIdSizeBits + kMaxIndexIdSizeBits) | (objectStoreIdString.size() - 1) << kMaxIndexIdSizeBits | (indexIdString.size() - 1); 1088 COMPILE_ASSERT(kMaxDatabaseIdSizeBits + kMaxObjectStoreIdSizeBits + kMaxIndexIdSizeBits == sizeof(firstByte) * 8, CANT_ENCODE_IDS); 1023 1089 Vector<char, DefaultInlineBufferSize> ret; 1024 1090 ret.append(firstByte); … … 1069 1135 Vector<char> SchemaVersionKey::encode() 1070 1136 { 1071 KeyPrefix prefix(0, 0, 0); 1072 Vector<char> ret = prefix.encode(); 1137 Vector<char> ret = KeyPrefix::encodeEmpty(); 1073 1138 ret.append(encodeByte(SchemaVersionTypeByte)); 1074 1139 return ret; … … 1077 1142 Vector<char> MaxDatabaseIdKey::encode() 1078 1143 { 1079 KeyPrefix prefix(0, 0, 0); 1080 Vector<char> ret = prefix.encode(); 1144 Vector<char> ret = KeyPrefix::encodeEmpty(); 1081 1145 ret.append(encodeByte(MaxDatabaseIdTypeByte)); 1082 1146 return ret; … … 1085 1149 Vector<char> DataVersionKey::encode() 1086 1150 { 1087 KeyPrefix prefix(0, 0, 0); 1088 Vector<char> ret = prefix.encode(); 1151 Vector<char> ret = KeyPrefix::encodeEmpty(); 1089 1152 ret.append(encodeByte(DataVersionTypeByte)); 1090 1153 return ret; … … 1117 1180 Vector<char> DatabaseFreeListKey::encode(int64_t databaseId) 1118 1181 { 1119 KeyPrefix prefix(0, 0, 0); 1120 Vector<char> ret = prefix.encode(); 1182 Vector<char> ret = KeyPrefix::encodeEmpty(); 1121 1183 ret.append(encodeByte(DatabaseFreeListTypeByte)); 1122 1184 ret.append(encodeVarInt(databaseId)); … … 1165 1227 Vector<char> DatabaseNameKey::encode(const String& origin, const String& databaseName) 1166 1228 { 1167 KeyPrefix prefix(0, 0, 0); 1168 Vector<char> ret = prefix.encode(); 1229 Vector<char> ret = KeyPrefix::encodeEmpty(); 1169 1230 ret.append(encodeByte(DatabaseNameTypeByte)); 1170 1231 ret.append(encodeStringWithLength(origin)); … … 1193 1254 Vector<char> DatabaseMetaDataKey::encode(int64_t databaseId, MetaDataType metaDataType) 1194 1255 { 1195 KeyPrefix prefix(databaseId , 0, 0);1256 KeyPrefix prefix(databaseId); 1196 1257 Vector<char> ret = prefix.encode(); 1197 1258 ret.append(encodeByte(metaDataType)); … … 1232 1293 Vector<char> ObjectStoreMetaDataKey::encode(int64_t databaseId, int64_t objectStoreId, unsigned char metaDataType) 1233 1294 { 1234 KeyPrefix prefix(databaseId , 0, 0);1295 KeyPrefix prefix(databaseId); 1235 1296 Vector<char> ret = prefix.encode(); 1236 1297 ret.append(encodeByte(ObjectStoreMetaDataTypeByte)); … … 1307 1368 Vector<char> IndexMetaDataKey::encode(int64_t databaseId, int64_t objectStoreId, int64_t indexId, unsigned char metaDataType) 1308 1369 { 1309 KeyPrefix prefix(databaseId , 0, 0);1370 KeyPrefix prefix(databaseId); 1310 1371 Vector<char> ret = prefix.encode(); 1311 1372 ret.append(encodeByte(IndexMetaDataTypeByte)); … … 1370 1431 Vector<char> ObjectStoreFreeListKey::encode(int64_t databaseId, int64_t objectStoreId) 1371 1432 { 1372 KeyPrefix prefix(databaseId , 0, 0);1433 KeyPrefix prefix(databaseId); 1373 1434 Vector<char> ret = prefix.encode(); 1374 1435 ret.append(encodeByte(ObjectStoreFreeListTypeByte)); … … 1427 1488 Vector<char> IndexFreeListKey::encode(int64_t databaseId, int64_t objectStoreId, int64_t indexId) 1428 1489 { 1429 KeyPrefix prefix(databaseId , 0, 0);1490 KeyPrefix prefix(databaseId); 1430 1491 Vector<char> ret = prefix.encode(); 1431 1492 ret.append(encodeByte(IndexFreeListTypeByte)); … … 1483 1544 Vector<char> ObjectStoreNamesKey::encode(int64_t databaseId, const String& objectStoreName) 1484 1545 { 1485 KeyPrefix prefix(databaseId , 0, 0);1546 KeyPrefix prefix(databaseId); 1486 1547 Vector<char> ret = prefix.encode(); 1487 1548 ret.append(encodeByte(ObjectStoreNamesTypeByte)); … … 1526 1587 Vector<char> IndexNamesKey::encode(int64_t databaseId, int64_t objectStoreId, const String& indexName) 1527 1588 { 1528 KeyPrefix prefix(databaseId , 0, 0);1589 KeyPrefix prefix(databaseId); 1529 1590 Vector<char> ret = prefix.encode(); 1530 1591 ret.append(encodeByte(IndexNamesKeyTypeByte)); … … 1558 1619 Vector<char> ObjectStoreDataKey::encode(int64_t databaseId, int64_t objectStoreId, const Vector<char> encodedUserKey) 1559 1620 { 1560 KeyPrefix prefix( databaseId, objectStoreId, SpecialIndexNumber);1621 KeyPrefix prefix(KeyPrefix::createWithSpecialIndex(databaseId, objectStoreId, SpecialIndexNumber)); 1561 1622 Vector<char> ret = prefix.encode(); 1562 1623 ret.append(encodedUserKey); … … 1600 1661 Vector<char> ExistsEntryKey::encode(int64_t databaseId, int64_t objectStoreId, const Vector<char>& encodedKey) 1601 1662 { 1602 KeyPrefix prefix( databaseId, objectStoreId, SpecialIndexNumber);1663 KeyPrefix prefix(KeyPrefix::createWithSpecialIndex(databaseId, objectStoreId, SpecialIndexNumber)); 1603 1664 Vector<char> ret = prefix.encode(); 1604 1665 ret.append(encodedKey); -
trunk/Source/WebCore/Modules/indexeddb/IDBLevelDBCoding.h
r145385 r145435 55 55 bool decodeBool(const char* begin, const char* end); 56 56 Vector<char> encodeInt(int64_t); 57 inline Vector<char> encodeIntSafely(int64_t nParam, size_t max) 58 { 59 ASSERT(static_cast<size_t>(nParam) <= max); 60 return encodeInt(nParam); 61 } 57 62 int64_t decodeInt(const char* begin, const char* end); 58 63 Vector<char> encodeVarInt(int64_t); … … 78 83 public: 79 84 KeyPrefix(); 85 explicit KeyPrefix(int64_t databaseId); 86 KeyPrefix(int64_t databaseId, int64_t objectStoreId); 80 87 KeyPrefix(int64_t databaseId, int64_t objectStoreId, int64_t indexId); 88 static KeyPrefix createWithSpecialIndex(int64_t databaseId, int64_t objectStoreId, int64_t indexId); 81 89 82 90 static const char* decode(const char* start, const char* limit, KeyPrefix* result); 83 91 Vector<char> encode() const; 92 static Vector<char> encodeEmpty(); 84 93 int compare(const KeyPrefix& other) const; 85 94 … … 93 102 }; 94 103 104 static const size_t kMaxDatabaseIdSizeBits = 3; 105 static const size_t kMaxObjectStoreIdSizeBits = 3; 106 static const size_t kMaxIndexIdSizeBits = 2; 107 108 static const size_t kMaxDatabaseIdSizeBytes = 1ULL << kMaxDatabaseIdSizeBits; // 8 109 static const size_t kMaxObjectStoreIdSizeBytes = 1ULL << kMaxObjectStoreIdSizeBits; // 8 110 static const size_t kMaxIndexIdSizeBytes = 1ULL << kMaxIndexIdSizeBits; // 4 111 112 static const size_t kMaxDatabaseIdBits = kMaxDatabaseIdSizeBytes * 8 - 1; // 63 113 static const size_t kMaxObjectStoreIdBits = kMaxObjectStoreIdSizeBytes * 8 - 1; // 63 114 static const size_t kMaxIndexIdBits = kMaxIndexIdSizeBytes * 8 - 1; // 31 115 116 static const int64_t kMaxDatabaseId = (1ULL << kMaxDatabaseIdBits) - 1; // max signed int64_t 117 static const int64_t kMaxObjectStoreId = (1ULL << kMaxObjectStoreIdBits) - 1; // max signed int64_t 118 static const int64_t kMaxIndexId = (1ULL << kMaxIndexIdBits) - 1; // max signed int32_t 119 120 static bool isValidDatabaseId(int64_t databaseId); 121 static bool isValidObjectStoreId(int64_t indexId); 122 static bool isValidIndexId(int64_t indexId); 123 static bool validIds(int64_t databaseId, int64_t objectStoreId, int64_t indexId) 124 { 125 return isValidDatabaseId(databaseId) && isValidObjectStoreId(objectStoreId) && isValidIndexId(indexId); 126 } 127 static bool validIds(int64_t databaseId, int64_t objectStoreId) 128 { 129 return isValidDatabaseId(databaseId) && isValidObjectStoreId(objectStoreId); 130 } 131 95 132 Type type() const; 96 133 … … 100 137 101 138 static const int64_t InvalidId = -1; 139 140 private: 141 static Vector<char> encodeInternal(int64_t databaseId, int64_t objectStoreId, int64_t indexId); 142 // Special constructor for createWithSpecialIndex() 143 KeyPrefix(Type, int64_t databaseId, int64_t objectStoreId, int64_t indexId); 102 144 }; 103 145 -
trunk/Source/WebCore/Modules/indexeddb/IDBObjectStoreBackendImpl.cpp
r145385 r145435 65 65 int64_t indexId = m_indexMetadata.id; 66 66 for (size_t i = 0; i < m_indexKeys.size(); ++i) { 67 backingStore.putIndexDataForRecord(transaction, databaseId, objectStoreId, indexId, *(m_indexKeys)[i].get(), recordIdentifier); 67 bool ok = backingStore.putIndexDataForRecord(transaction, databaseId, objectStoreId, indexId, *(m_indexKeys)[i].get(), recordIdentifier); 68 // This should have already been verified as a valid write during verifyIndexKeys. 69 ASSERT_UNUSED(ok, ok); 68 70 } 69 71 } -
trunk/Source/WebKit/chromium/ChangeLog
r145406 r145435 1 2013-03-11 Alec Flett <alecflett@chromium.org> 2 3 IndexedDB: Protect against key prefix overflows 4 https://bugs.webkit.org/show_bug.cgi?id=111138 5 6 Reviewed by Tony Chang. 7 8 Add tests for invalid indexIds in basic get/put operations. 9 1 10 2013-03-11 Xiyuan Xia <xiyuan@chromium.org> 2 11 -
trunk/Source/WebKit/chromium/tests/IDBBackingStoreTest.cpp
r145385 r145435 29 29 30 30 #include "IDBFactoryBackendImpl.h" 31 #include "IDBLevelDBCoding.h" 31 32 #include "SharedBuffer.h" 32 33 … … 37 38 38 39 using namespace WebCore; 40 using IDBLevelDBCoding::KeyPrefix; 39 41 40 42 namespace { … … 54 56 const char rawValue1[] = "value1"; 55 57 const char rawValue2[] = "value2"; 58 const char rawValue3[] = "value3"; 56 59 m_value1.append(rawValue1, sizeof(rawValue1)); 57 60 m_value2.append(rawValue2, sizeof(rawValue2)); 61 m_value3.append(rawValue3, sizeof(rawValue3)); 58 62 m_key1 = IDBKey::createNumber(99); 59 63 m_key2 = IDBKey::createString("key2"); 64 m_key3 = IDBKey::createString("key3"); 60 65 } 61 66 … … 66 71 RefPtr<IDBKey> m_key1; 67 72 RefPtr<IDBKey> m_key2; 73 RefPtr<IDBKey> m_key3; 68 74 Vector<char> m_value1; 69 75 Vector<char> m_value2; 76 Vector<char> m_value3; 70 77 }; 71 78 … … 97 104 const int64_t highDatabaseId = 1ULL << 35; 98 105 const int64_t highObjectStoreId = 1ULL << 39; 106 // indexIds are capped at 32 bits for storage purposes. 107 const int64_t highIndexId = 1ULL << 29; 108 109 const int64_t invalidHighIndexId = 1ULL << 37; 110 111 const RefPtr<IDBKey> indexKey = m_key2; 112 Vector<char> indexKeyRaw = IDBLevelDBCoding::encodeIDBKey(*indexKey); 99 113 { 100 114 IDBBackingStore::Transaction transaction1(m_backingStore.get()); … … 103 117 bool ok = m_backingStore->putRecord(&transaction1, highDatabaseId, highObjectStoreId, *m_key1.get(), SharedBuffer::create(m_value1.data(), m_value1.size()), &record); 104 118 EXPECT_TRUE(ok); 119 120 ok = m_backingStore->putIndexDataForRecord(&transaction1, highDatabaseId, highObjectStoreId, invalidHighIndexId, *indexKey, record); 121 EXPECT_FALSE(ok); 122 123 ok = m_backingStore->putIndexDataForRecord(&transaction1, highDatabaseId, highObjectStoreId, highIndexId, *indexKey, record); 124 EXPECT_TRUE(ok); 125 105 126 ok = transaction1.commit(); 106 127 EXPECT_TRUE(ok); … … 113 134 bool ok = m_backingStore->getRecord(&transaction2, highDatabaseId, highObjectStoreId, *m_key1.get(), resultValue); 114 135 EXPECT_TRUE(ok); 136 EXPECT_EQ(m_value1, resultValue); 137 138 RefPtr<IDBKey> newPrimaryKey; 139 ok = m_backingStore->getPrimaryKeyViaIndex(&transaction2, highDatabaseId, highObjectStoreId, invalidHighIndexId, *indexKey, newPrimaryKey); 140 EXPECT_FALSE(ok); 141 142 ok = m_backingStore->getPrimaryKeyViaIndex(&transaction2, highDatabaseId, highObjectStoreId, highIndexId, *indexKey, newPrimaryKey); 143 EXPECT_TRUE(ok); 144 EXPECT_TRUE(newPrimaryKey->isEqual(m_key1.get())); 145 115 146 ok = transaction2.commit(); 116 147 EXPECT_TRUE(ok); 117 EXPECT_EQ(m_value1, resultValue); 118 } 148 } 149 } 150 151 // Make sure that other invalid ids do not crash. 152 TEST_F(IDBBackingStoreTest, InvalidIds) 153 { 154 // valid ids for use when testing invalid ids 155 const int64_t databaseId = 1; 156 const int64_t objectStoreId = 1; 157 const int64_t indexId = IDBLevelDBCoding::MinimumIndexId; 158 const int64_t invalidLowIndexId = 19; // indexIds must be > IDBLevelDBCoding::MinimumIndexId 159 160 const RefPtr<SharedBuffer> value = SharedBuffer::create(m_value1.data(), m_value1.size()); 161 Vector<char> resultValue; 162 163 IDBBackingStore::Transaction transaction1(m_backingStore.get()); 164 transaction1.begin(); 165 166 IDBBackingStore::RecordIdentifier record; 167 bool ok = m_backingStore->putRecord(&transaction1, databaseId, KeyPrefix::InvalidId, *m_key1.get(), value, &record); 168 EXPECT_FALSE(ok); 169 ok = m_backingStore->putRecord(&transaction1, databaseId, 0, *m_key1.get(), value, &record); 170 EXPECT_FALSE(ok); 171 ok = m_backingStore->putRecord(&transaction1, KeyPrefix::InvalidId, objectStoreId, *m_key1.get(), value, &record); 172 EXPECT_FALSE(ok); 173 ok = m_backingStore->putRecord(&transaction1, 0, objectStoreId, *m_key1.get(), value, &record); 174 EXPECT_FALSE(ok); 175 176 ok = m_backingStore->getRecord(&transaction1, databaseId, KeyPrefix::InvalidId, *m_key1.get(), resultValue); 177 EXPECT_FALSE(ok); 178 ok = m_backingStore->getRecord(&transaction1, databaseId, 0, *m_key1.get(), resultValue); 179 EXPECT_FALSE(ok); 180 ok = m_backingStore->getRecord(&transaction1, KeyPrefix::InvalidId, objectStoreId, *m_key1.get(), resultValue); 181 EXPECT_FALSE(ok); 182 ok = m_backingStore->getRecord(&transaction1, 0, objectStoreId, *m_key1.get(), resultValue); 183 EXPECT_FALSE(ok); 184 185 RefPtr<IDBKey> newPrimaryKey; 186 ok = m_backingStore->getPrimaryKeyViaIndex(&transaction1, databaseId, objectStoreId, KeyPrefix::InvalidId, *m_key1, newPrimaryKey); 187 EXPECT_FALSE(ok); 188 ok = m_backingStore->getPrimaryKeyViaIndex(&transaction1, databaseId, objectStoreId, invalidLowIndexId, *m_key1, newPrimaryKey); 189 EXPECT_FALSE(ok); 190 ok = m_backingStore->getPrimaryKeyViaIndex(&transaction1, databaseId, objectStoreId, 0, *m_key1, newPrimaryKey); 191 EXPECT_FALSE(ok); 192 193 ok = m_backingStore->getPrimaryKeyViaIndex(&transaction1, KeyPrefix::InvalidId, objectStoreId, indexId, *m_key1, newPrimaryKey); 194 EXPECT_FALSE(ok); 195 ok = m_backingStore->getPrimaryKeyViaIndex(&transaction1, databaseId, KeyPrefix::InvalidId, indexId, *m_key1, newPrimaryKey); 196 EXPECT_FALSE(ok); 119 197 } 120 198 … … 167 245 EXPECT_EQ(databaseId, database.id); 168 246 169 m_backingStore->getObjectStores(database.id, &database.objectStores); 247 ok = m_backingStore->getObjectStores(database.id, &database.objectStores); 248 EXPECT_TRUE(ok); 170 249 171 250 EXPECT_EQ(1, database.objectStores.size()); -
trunk/Source/WebKit/chromium/tests/IDBFakeBackingStore.h
r145385 r145435 42 42 virtual bool createObjectStore(Transaction*, int64_t databaseId, int64_t objectStoreId, const String& name, const IDBKeyPath&, bool autoIncrement) OVERRIDE { return false; }; 43 43 44 virtual void clearObjectStore(Transaction*, int64_t databaseId, int64_t objectStoreId) OVERRIDE {}45 virtual void deleteRecord(Transaction*, int64_t databaseId, int64_t objectStoreId, const RecordIdentifier&) OVERRIDE {}44 virtual bool clearObjectStore(Transaction*, int64_t databaseId, int64_t objectStoreId) OVERRIDE { return false; } 45 virtual bool deleteRecord(Transaction*, int64_t databaseId, int64_t objectStoreId, const RecordIdentifier&) OVERRIDE { return false; } 46 46 virtual bool getKeyGeneratorCurrentNumber(Transaction*, int64_t databaseId, int64_t objectStoreId, int64_t& currentNumber) OVERRIDE { return true; } 47 47 virtual bool maybeUpdateKeyGeneratorCurrentNumber(Transaction*, int64_t databaseId, int64_t objectStoreId, int64_t newNumber, bool checkCurrent) OVERRIDE { return true; } … … 49 49 50 50 virtual bool createIndex(Transaction*, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const String& name, const IDBKeyPath&, bool isUnique, bool isMultiEntry) OVERRIDE { return false; }; 51 virtual void deleteIndex(Transaction*, int64_t databaseId, int64_t objectStoreId, int64_t indexId) OVERRIDE {}52 virtual void putIndexDataForRecord(Transaction*, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey&, const RecordIdentifier&) OVERRIDE {}51 virtual bool deleteIndex(Transaction*, int64_t databaseId, int64_t objectStoreId, int64_t indexId) OVERRIDE { return false; } 52 virtual bool putIndexDataForRecord(Transaction*, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey&, const RecordIdentifier&) OVERRIDE { return false; } 53 53 54 54 virtual PassRefPtr<Cursor> openObjectStoreKeyCursor(Transaction*, int64_t databaseId, int64_t objectStoreId, const IDBKeyRange*, IndexedDB::CursorDirection) OVERRIDE { return PassRefPtr<Cursor>(); } -
trunk/Source/WebKit/chromium/tests/IDBLevelDBCodingTest.cpp
r143347 r145435 102 102 } 103 103 } 104 104 105 105 TEST(IDBLevelDBCodingTest, EncodeBool) 106 106 { … … 712 712 keys.append(IndexDataKey::encode(1, 1, 31, minIDBKey(), minIDBKey(), 0)); 713 713 keys.append(IndexDataKey::encode(1, 2, 30, minIDBKey(), minIDBKey(), 0)); 714 keys.append(IndexDataKey::encodeMaxKey(1, 2, INT32_MAX ));714 keys.append(IndexDataKey::encodeMaxKey(1, 2, INT32_MAX - 1)); 715 715 716 716 for (size_t i = 0; i < keys.size(); ++i) {
Note: See TracChangeset
for help on using the changeset viewer.