RESOLVED FIXED 222340
Streamline ImageData size calculations and handle out-of-memory
https://bugs.webkit.org/show_bug.cgi?id=222340
Summary Streamline ImageData size calculations and handle out-of-memory
Darin Adler
Reported 2021-02-23 18:42:51 PST
Streamline ImageData size calculations and handle out-of-memory
Attachments
Patch (5.44 KB, patch)
2021-02-24 09:57 PST, Darin Adler
ggaren: review+
ews-feeder: commit-queue-
Patch (5.49 KB, patch)
2021-02-24 16:35 PST, Darin Adler
no flags
Darin Adler
Comment 1 2021-02-24 09:57:13 PST
Darin Adler
Comment 2 2021-02-24 09:57:47 PST
Geoffrey Garen
Comment 3 2021-02-24 10:18:43 PST
Comment on attachment 421418 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=421418&action=review r=me > Source/WebCore/html/ImageData.cpp:69 > RefPtr<ImageData> ImageData::create(const IntSize& size) > { > - Checked<int, RecordOverflow> dataSize = 4; > - dataSize *= size.width(); > - dataSize *= size.height(); > + auto dataSize = ImageData::dataSize(size); > if (dataSize.hasOverflowed()) > return nullptr; > - > - return adoptRef(*new ImageData(size)); > + return adoptRef(*new ImageData(size, Uint8ClampedArray::createUninitialized(dataSize.unsafeGet()))); > } It's kind of funny that this function will safely return null on absurd sizes that overflow, but crash on more modest sizes that trigger allocation failure. Should we crash on overflow too? Or return null on allocation failure instead?
Darin Adler
Comment 4 2021-02-24 10:32:21 PST
Comment on attachment 421418 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=421418&action=review >> Source/WebCore/html/ImageData.cpp:69 >> } > > It's kind of funny that this function will safely return null on absurd sizes that overflow, but crash on more modest sizes that trigger allocation failure. Should we crash on overflow too? Or return null on allocation failure instead? Those thoughts occurred to me, too. I wasn’t sure enough about where and how this function is used to make a good decision. Let me research that now.
Darin Adler
Comment 5 2021-02-24 11:28:44 PST
Comment on attachment 421418 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=421418&action=review >>> Source/WebCore/html/ImageData.cpp:69 >>> } >> >> It's kind of funny that this function will safely return null on absurd sizes that overflow, but crash on more modest sizes that trigger allocation failure. Should we crash on overflow too? Or return null on allocation failure instead? > > Those thoughts occurred to me, too. I wasn’t sure enough about where and how this function is used to make a good decision. Let me research that now. Looking into this has led me down a bit of a rabbit hole. I discovered that CanvasRenderingContext2D calls this in response to calls from JavaScript and thus should be using a create function that can return an exception. That needs to be fixed, which might change the ImageData class interface to add more create functions, or we might just use the JavaScript-friendly one. Maybe it needs a name different from just "create" to make it clear that it tries or to make it clear that it’s for JavaScript-exposed uses. I’m not sure I should make any behavior change to this function in this patch, though. It seems logical that returning nullptr would be OK, but I am not really sure. One of the uses is in SerializedScriptValue, and I’m not sure are what the implications there; probably fine to fail cleanly if out of memory? It might be indirectly JavaScript-exposed?
Darin Adler
Comment 6 2021-02-24 16:06:17 PST
Comment on attachment 421418 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=421418&action=review >>>> Source/WebCore/html/ImageData.cpp:69 >>>> } >>> >>> It's kind of funny that this function will safely return null on absurd sizes that overflow, but crash on more modest sizes that trigger allocation failure. Should we crash on overflow too? Or return null on allocation failure instead? >> >> Those thoughts occurred to me, too. I wasn’t sure enough about where and how this function is used to make a good decision. Let me research that now. > > Looking into this has led me down a bit of a rabbit hole. > > I discovered that CanvasRenderingContext2D calls this in response to calls from JavaScript and thus should be using a create function that can return an exception. That needs to be fixed, which might change the ImageData class interface to add more create functions, or we might just use the JavaScript-friendly one. Maybe it needs a name different from just "create" to make it clear that it tries or to make it clear that it’s for JavaScript-exposed uses. > > I’m not sure I should make any behavior change to this function in this patch, though. It seems logical that returning nullptr would be OK, but I am not really sure. One of the uses is in SerializedScriptValue, and I’m not sure are what the implications there; probably fine to fail cleanly if out of memory? It might be indirectly JavaScript-exposed? Turns out that changing behavior here, to return nullptr, fixes a failing regression test. So I’m going to change as you suggested (your second suggestion, return null). There is still follow up needed to make sure we consistently raise an exception rather than failing silently or returning null in various JavaScript contexts. And I suppose some tiny risk that returning nullptr rather than crashing is worse in some way.
Darin Adler
Comment 7 2021-02-24 16:35:04 PST
Darin Adler
Comment 8 2021-02-25 13:10:49 PST
Note You need to log in before you can comment on or make changes to this bug.