Bug 92725

Summary: IndexedDB: ObjectStoreMetaDataKey::m_metaDataType should use byte type
Product: WebKit Reporter: Xingnan Wang <xingnan.wang>
Component: WebCore Misc.Assignee: Nobody <webkit-unassigned>
Status: RESOLVED FIXED    
Severity: Normal CC: alecflett, dgrogan, haraken, jochen, jsbell, rniwa, webkit.review.bot
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: Unspecified   
OS: Unspecified   
Attachments:
Description Flags
Patch
none
Patch
none
Patch
none
Patch none

Description Xingnan Wang 2012-07-31 01:11:46 PDT
Use unsigned char instead of integer.
Comment 1 Xingnan Wang 2012-07-31 01:15:44 PDT
Created attachment 155461 [details]
Patch
Comment 2 Kentaro Hara 2012-07-31 01:26:39 PDT
Comment on attachment 155461 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=155461&action=review

Looks good.

> Source/WebCore/ChangeLog:8
> +        No new tests - Covered by existing tests.

Would you list up a couple of existing tests here?

> Source/WebCore/Modules/indexeddb/IDBLevelDBCoding.cpp:1089
> +    result->m_metaDataType = *p++;

Shall we implement decodeByte()? (For consistency with existing encodeByte().)
Comment 3 Xingnan Wang 2012-07-31 01:46:30 PDT
Comment on attachment 155461 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=155461&action=review

>> Source/WebCore/ChangeLog:8
>> +        No new tests - Covered by existing tests.
> 
> Would you list up a couple of existing tests here?

All right. It`s in the encoding/decoding level of object store,I think most of the test cases could cover this.

>> Source/WebCore/Modules/indexeddb/IDBLevelDBCoding.cpp:1089
>> +    result->m_metaDataType = *p++;
> 
> Shall we implement decodeByte()? (For consistency with existing encodeByte().)

Good suggestion.
Comment 4 Joshua Bell 2012-07-31 07:22:26 PDT
Comment on attachment 155461 [details]
Patch

This looks like it will fail for existing stored data on disk.  Some back compat mechanism is necessary. 

I'm on vacation at the moment. Please CC dgrogan and alecflett for feedback.
Comment 5 Joshua Bell 2012-07-31 07:23:58 PDT
(Ah, they already are CC'd. I'm reading this on my phone, sorry.)
Comment 6 David Grogan 2012-07-31 09:54:18 PDT
Comment on attachment 155461 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=155461&action=review

>>> Source/WebCore/Modules/indexeddb/IDBLevelDBCoding.cpp:1089
>>> +    result->m_metaDataType = *p++;
>> 
>> Shall we implement decodeByte()? (For consistency with existing encodeByte().)
> 
> Good suggestion.

For compatibility with existing databases, you can maybe detect here whether it's a byte or var int.  I don't know if that's bulletproof though.  Or you can look into doing a schema upgrade in IDBLevelDBBackingStore::setUpMetadata.  That might be slow.  Some experimentation might be needed.
Comment 7 Xingnan Wang 2012-07-31 20:00:22 PDT
(In reply to comment #6)
> (From update of attachment 155461 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=155461&action=review
> 
> >>> Source/WebCore/Modules/indexeddb/IDBLevelDBCoding.cpp:1089
> >>> +    result->m_metaDataType = *p++;
> >> 
> >> Shall we implement decodeByte()? (For consistency with existing encodeByte().)
> > 
> > Good suggestion.
> 
> For compatibility with existing databases, you can maybe detect here whether it's a byte or var int.  I don't know if that's bulletproof though.  Or you can look into doing a schema upgrade in IDBLevelDBBackingStore::setUpMetadata.  That might be slow.  Some experimentation might be needed.

m_metaDataType is always less than 8, which is encoded by encodeVarInt() with only one byte. Also encodeByte() uses one byte to store the data with the same way. So could we think it would not fail for the existing data in disk?
Comment 8 Joshua Bell 2012-07-31 20:12:42 PDT
Comment on attachment 155461 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=155461&action=review

You're right - the range of existing values that are used for the ObjectMetaDataType should encode identically for VarInt and Byte since they are <= 127. So this should be safe. (A webkit_unit_test case could be added for that, validating that the encodings are the same for the current roster of values.) Removing my paranoid objection.

> Source/WebCore/Modules/indexeddb/IDBLevelDBCoding.cpp:67
> +//     The prefix is followed by a type byte, then a variable-length integer, and then another variable-length integer.

That should end with "and then another type byte."
Comment 9 Xingnan Wang 2012-07-31 23:42:18 PDT
Created attachment 155729 [details]
Patch
Comment 10 Xingnan Wang 2012-07-31 23:44:46 PDT
(In reply to comment #9)
> Created an attachment (id=155729) [details]
> Patch

Updated the patch as your comments, thanks.
Comment 11 Kentaro Hara 2012-07-31 23:59:57 PDT
Comment on attachment 155729 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=155729&action=review

LGTM. If jsbell@ says OK, I'm happy to r+ it.

> Source/WebCore/Modules/indexeddb/IDBLevelDBCoding.cpp:180
> +    ASSERT(p < limit);
> +    if (p >= limit)

This looks strange. We don't need both. (Although some code in IDBLevelDBCoding.cpp already use both.)

If 'p >= limit' must not happen, please remove 'if (p >= limit)'. If it can happen, please remove ASSERT(p < limit). (I think that removing ASSERT() looks reasonable in this case.)
Comment 12 Xingnan Wang 2012-08-01 01:30:59 PDT
Created attachment 155750 [details]
Patch
Comment 13 Joshua Bell 2012-08-01 08:31:21 PDT
(In reply to comment #11)
> (From update of attachment 155729 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=155729&action=review
> 
> LGTM. If jsbell@ says OK, I'm happy to r+ it.

I'm going to build the Chromium tests locally with this patch first. Working on that now.
 
> > Source/WebCore/Modules/indexeddb/IDBLevelDBCoding.cpp:180
> > +    ASSERT(p < limit);
> > +    if (p >= limit)
> 
> This looks strange. We don't need both. (Although some code in IDBLevelDBCoding.cpp already use both.)
> 
> If 'p >= limit' must not happen, please remove 'if (p >= limit)'. If it can happen, please remove ASSERT(p < limit). (I think that removing ASSERT() looks reasonable in this case.)

As an FYI:

Although much of this code predates me, I believe the intent of these redundant tests is to serve two different purposes. The ASSERTs are present to catch errors during development, e.g. when we're refactoring code, modifying constants, etc. The non-debug tests are in there to catch runtime errors due to corrupt data (e.g. actual on-disk corruption, uncaught bugs that write bad data, etc). 

I agree that's not a very good style, and I'm fine with leaving out the ASSERT here, as the error handling in this file needs a cleanup pass. We should probably switch the ASSERTs over to something like a custom macro that does ASSERT in Debug but also does a LOG_ERROR and stats reporting in Release builds, in addition to returning the error code.
Comment 14 Joshua Bell 2012-08-01 09:22:59 PDT
Comment on attachment 155750 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=155750&action=review

LGTM with one change suggestion.

Also, I think there should be a Source/WebKit/chromium/ChangeLog entry. Either just add it manually, or remove the Source/WebCore/ChangeLog entry, run webkit-patch prepare 92725, then re-apply the Source/WebCore/ChangeLog entry (I don't know if there's a faster way to prepare just the missing ChangeLogs)

> Source/WebKit/chromium/tests/IDBLevelDBCodingTest.cpp:93
> +#ifdef NDEBUG

These NDEBUG guards should not be necessary here. 

We use them in the "Int" tests due to ASSERTs that guard against using data with the high bit set (since the methods are not correctly using signed/unsigned types), but wanted to ensure the correct behavior in the test. (I can dig up the bug number if desired, there was a long discussion.)

The new decodeByte function correctly takes an unsigned char, though, so it doesn't matter here.

> Source/WebKit/chromium/tests/IDBLevelDBCodingTest.cpp:708
> +TEST(IDBLevelDBCodingTest, EncodeVarIntVSEncodeByteTest)

Thanks a bunch for adding this.
Comment 15 Xingnan Wang 2012-08-01 19:07:40 PDT
Created attachment 155949 [details]
Patch
Comment 16 Xingnan Wang 2012-08-01 19:10:08 PDT
Comment on attachment 155750 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=155750&action=review

>> Source/WebKit/chromium/tests/IDBLevelDBCodingTest.cpp:93
>> +#ifdef NDEBUG
> 
> These NDEBUG guards should not be necessary here. 
> 
> We use them in the "Int" tests due to ASSERTs that guard against using data with the high bit set (since the methods are not correctly using signed/unsigned types), but wanted to ensure the correct behavior in the test. (I can dig up the bug number if desired, there was a long discussion.)
> 
> The new decodeByte function correctly takes an unsigned char, though, so it doesn't matter here.

Removed this one.

>> Source/WebKit/chromium/tests/IDBLevelDBCodingTest.cpp:708
>> +TEST(IDBLevelDBCodingTest, EncodeVarIntVSEncodeByteTest)
> 
> Thanks a bunch for adding this.

Thanks for your review, updated the patch.
Comment 17 Kentaro Hara 2012-08-01 19:10:43 PDT
Comment on attachment 155949 [details]
Patch

Looks OK
Comment 18 WebKit Review Bot 2012-08-01 20:08:27 PDT
Comment on attachment 155949 [details]
Patch

Clearing flags on attachment: 155949

Committed r124402: <http://trac.webkit.org/changeset/124402>
Comment 19 WebKit Review Bot 2012-08-01 20:08:31 PDT
All reviewed patches have been landed.  Closing bug.
Comment 20 Ryosuke Niwa 2012-08-01 22:59:21 PDT
Chromium Android build fix landed in http://trac.webkit.org/changeset/124411.