Bug 148620 - Undefined behavior in SQLiteStatement::getColumnText
Summary: Undefined behavior in SQLiteStatement::getColumnText
Status: RESOLVED INVALID
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebCore Misc. (show other bugs)
Version: Other
Hardware: PC Linux
: P2 Normal
Assignee: Michael Catanzaro
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-08-30 14:40 PDT by Michael Catanzaro
Modified: 2015-12-03 02:44 PST (History)
5 users (show)

See Also:


Attachments
Patch (2.48 KB, patch)
2015-08-30 14:58 PDT, Michael Catanzaro
darin: review-
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Catanzaro 2015-08-30 14:40:28 PDT
There is undefined behavior in SQLiteStatement::getColumnText. sqlite3_column_text16 can trigger an internal type conversion, which would invalidate the result of sqlite3_column_bytes16. Here they are called as two different parameters to the same function, so the order is undefined. But the correctness of this function relies on sqlite3_column_text16 being called before sqlite3_column_bytes16.
Comment 1 Michael Catanzaro 2015-08-30 14:58:01 PDT
Created attachment 260253 [details]
Patch
Comment 2 Michael Catanzaro 2015-09-19 11:05:48 PDT
Note: I checked the rest of this file to make sure this pattern doesn't occur elsewhere.
Comment 3 Michael Catanzaro 2015-12-02 08:38:26 PST
(Easy review here!)
Comment 4 Brady Eidson 2015-12-02 11:30:50 PST
(In reply to comment #3)
> (Easy review here!)

This is such a subtle thing, I think it'd be awesome if the theoretical issue could be proven with a test.
Comment 5 Darin Adler 2015-12-02 13:58:33 PST
Comment on attachment 260253 [details]
Patch

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

> Source/WebCore/ChangeLog:15
> +        There is undefined behavior in SQLiteStatement::getColumnText. sqlite3_column_text16 can
> +        trigger an internal type conversion, which would invalidate the result of
> +        sqlite3_column_bytes16. Here they are called as two different parameters to the same
> +        function, so the order of execution is undefined. But the correctness of this function
> +        relies on sqlite3_column_text16 being called before sqlite3_column_bytes16. Otherwise, we'll
> +        wind up either truncating the string we create if the size is too short, or else creating it
> +        with random memory if it's too big. Fix this by calling the functions sequentially instead
> +        of doing it all in one statement.

My reading of <https://sqlite.org/c3ref/column_blob.html> says this analysis is incorrect. Both sqlite3_column_text16 and sqlite3_column_bytes16 convert the string to UTF-16. It doesn’t matter which is called first.

It’s true that the page recommends calling sqlite3_column_text16 first and then sqlite3_column_bytes16, but if you read carefully you’ll see that it’s equally safe to call sqlite3_column_bytes16 first and then sqlite3_column_text16, as long as you don’t call other functions.

I think there is no bug here.

> Source/WebCore/platform/sql/SQLiteStatement.cpp:346
> +    // size of the result, so it must strictly preceed the call to sqlite3_column_bytes16.

Spelling error here: precede is misspelled as “preceed”

> Source/WebCore/platform/sql/SQLiteStatement.cpp:349
> +    int length = sqlite3_column_bytes16(m_statement, col) / sizeof(UChar);
> +    return String(text, length);

I wouldn’t split these into two separate lines.
Comment 6 Darin Adler 2015-12-02 14:00:21 PST
(In reply to comment #4)
> This is such a subtle thing, I think it'd be awesome if the theoretical
> issue could be proven with a test.

I don’t think that would be practical, because the ordering of evaluation of function arguments is undefined and so it’s compiler-dependent. If there was a bug here, it still might be impossible to reproduce on any given compiler.

But as I said above, I don’t think there is a bug here.
Comment 7 Michael Catanzaro 2015-12-03 02:44:32 PST
I think you're right. Thanks for the thorough review!