RESOLVED FIXED 226557
-Warray-bounds, -Wstringop-truncation, -Wstringop-overread warnings in Packed.h
https://bugs.webkit.org/show_bug.cgi?id=226557
Summary -Warray-bounds, -Wstringop-truncation, -Wstringop-overread warnings in Packed.h
Michael Catanzaro
Reported 2021-06-02 15:41:34 PDT
Splitting this from bug #226193. We have a -Warray-bounds warning in Packed.h. Fortunately it's only triggered when compiling WebSocket.cpp, which is why it's not a more serious warning spam: [506/1614] Building CXX object Source/WebCore/CMakeFiles/...edSources/unified-sources/UnifiedSource-4babe430-49.cpp.o In file included from WTF/Headers/wtf/text/StringImpl.h:32, from WTF/Headers/wtf/text/WTFString.h:31, from ../../Source/WebCore/dom/Exception.h:30, from ../../Source/WebCore/dom/ExceptionOr.h:29, from ../../Source/WebCore/dom/Event.h:29, from ../../Source/WebCore/Modules/websockets/CloseEvent.h:33, from ../../Source/WebCore/Modules/websockets/CloseEvent.cpp:27, from WebCore/DerivedSources/unified-sources/UnifiedSource-4babe430-49.cpp:2: In member function ‘T* WTF::PackedAlignedPtr<T, <anonymous> >::get() const [with T = JSC::SharedArrayBufferContents; long unsigned int passedAlignment = 1]’, inlined from ‘WTF::PackedAlignedPtr<T, <anonymous> >::operator bool() const [with T = JSC::SharedArrayBufferContents; long unsigned int passedAlignment = 1]’ at WTF/Headers/wtf/Packed.h:188:48, inlined from ‘WTF::RefPtr<T, <template-parameter-1-2>, <template-parameter-1-3> >::operator WTF::RefPtr<T, <template-parameter-1-2>, <template-parameter-1-3> >::UnspecifiedBoolType() const [with T = JSC::SharedArrayBufferContents; _PtrTraits = WTF::PackedPtrTraits<JSC::SharedArrayBufferContents>; _RefDerefTraits = WTF::DefaultRefDerefTraits<JSC::SharedArrayBufferContents>]’ at WTF/Headers/wtf/RefPtr.h:91:57, inlined from ‘bool JSC::ArrayBufferContents::isShared() const’ at JavaScriptCore/PrivateHeaders/JavaScriptCore/ArrayBuffer.h:84:36, inlined from ‘bool JSC::ArrayBuffer::isShared() const’ at JavaScriptCore/PrivateHeaders/JavaScriptCore/ArrayBuffer.h:202:31, inlined from ‘WTF::RefPtr<JSC::ArrayBuffer> JSC::ArrayBufferView::unsharedBuffer() const’ at JavaScriptCore/PrivateHeaders/JavaScriptCore/ArrayBufferView.h:60:9, inlined from ‘WebCore::ExceptionOr<void> WebCore::WebSocket::send(JSC::ArrayBufferView&)’ at ../../Source/WebCore/Modules/websockets/WebSocket.cpp:389:52: WTF/Headers/wtf/Packed.h:140:15: warning: ‘void* memcpy(void*, const void*, size_t)’ offset [0, 5] is out of the bounds [0, 0] [-Warray-bounds] 140 | memcpy(&value, m_storage.data(), storageSize); | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Attachments
Patch (5.71 KB, patch)
2021-06-14 14:31 PDT, Michael Catanzaro
no flags
Patch (1.92 KB, patch)
2021-06-28 08:15 PDT, Michael Catanzaro
no flags
Patch (3.28 KB, patch)
2021-06-30 10:57 PDT, Michael Catanzaro
no flags
Patch (2.41 KB, patch)
2021-07-29 14:00 PDT, Michael Catanzaro
no flags
Patch (3.26 KB, patch)
2021-07-30 07:28 PDT, Michael Catanzaro
ews-feeder: commit-queue-
Patch (4.51 KB, patch)
2021-07-30 07:36 PDT, Michael Catanzaro
ews-feeder: commit-queue-
Patch (4.51 KB, patch)
2021-07-30 07:42 PDT, Michael Catanzaro
no flags
Patch (1.83 KB, patch)
2021-08-05 08:04 PDT, Michael Catanzaro
no flags
Patch (6.88 KB, patch)
2021-11-11 11:20 PST, Michael Catanzaro
no flags
Radar WebKit Bug Importer
Comment 1 2021-06-09 15:42:21 PDT
Michael Catanzaro
Comment 2 2021-06-14 13:35:33 PDT
OK, at first I thought this was yet another false-positive, but now I see why GCC is complaining. Here is PackedAlignedPtr::get in Packed.h: T* get() const { // FIXME: PackedPtr<> can load memory with one mov by checking page boundary. // https://bugs.webkit.org/show_bug.cgi?id=197754 uintptr_t value = 0; #if CPU(LITTLE_ENDIAN) memcpy(&value, m_storage.data(), storageSize); #else memcpy(bitwise_cast<uint8_t*>(&value) + (sizeof(void*) - storageSize), m_storage.data(), storageSize); #endif if (isAlignmentShiftProfitable) value <<= alignmentShiftSize; #if CPU(X86_64) && !(OS(DARWIN) || OS(LINUX) || OS(WINDOWS)) // The AMD specification requires that the most significant 16 // bits of any virtual address, bits 48 through 63, must be // copies of bit 47 (in a manner akin to sign extension). // // The above-named OSes will never allocate user space addresses // with bit 47 set, thus are already in canonical form. // // Reference: https://en.wikipedia.org/wiki/X86-64#Virtual_address_space_details constexpr unsigned shiftBits = countOfBits<uintptr_t> - OS_CONSTANT(EFFECTIVE_ADDRESS_WIDTH); value = (bitwise_cast<intptr_t>(value) << shiftBits) >> shiftBits; #endif return bitwise_cast<T*>(value); } The only lines that matter are here: uintptr_t value = 0; #if CPU(LITTLE_ENDIAN) memcpy(&value, m_storage.data(), storageSize); Here storageSize is 5, so we copy five bytes of data from m_storage.data() to &value, which the compiler expects to be an array but is actually a uintptr_t declared on the stack. So I guess the compiler is reasonable to treat one uintptr_t as a zero-length memory region and emit the warning. We know this ought to be OK for 64-bit systems because we know that uintptr_t will be 8-bytes long, so it's not really zero-length. It is clearly intentional, so the warning should be suppressed manually. The safety depends on (a) storageSize <= sizeof(uintptr_t) -- so maybe we should add a static_assert for that --, and (b) compiler not deciding the memcpy is undefined behavior that can be "optimized" away.
Michael Catanzaro
Comment 3 2021-06-14 14:31:43 PDT
EWS
Comment 4 2021-06-15 09:47:50 PDT
Committed r278878 (238821@main): <https://commits.webkit.org/238821@main> All reviewed patches have been landed. Closing bug and clearing flags on attachment 431366 [details].
Michael Catanzaro
Comment 5 2021-06-28 08:08:19 PDT
Reopening because I forgot to suppress the -Wstringop-overread warning that appears when the -Warray-bounds warning is suppressed. The analysis in comment #2 applies just the same to this: [2629/5494] Building CXX object Source...ources/UnifiedSource-4babe430-49.cpp.o In file included from WTF/Headers/wtf/text/StringImpl.h:32, from WTF/Headers/wtf/text/WTFString.h:31, from ../../Source/WebCore/dom/Exception.h:30, from ../../Source/WebCore/dom/ExceptionOr.h:29, from ../../Source/WebCore/dom/Event.h:29, from ../../Source/WebCore/Modules/websockets/CloseEvent.h:33, from ../../Source/WebCore/Modules/websockets/CloseEvent.cpp:27, from WebCore/DerivedSources/unified-sources/UnifiedSource-4babe430-49.cpp:1: In member function ‘T* WTF::PackedAlignedPtr<T, <anonymous> >::get() const [with T = JSC::SharedArrayBufferContents; long unsigned int passedAlignment = 1]’, inlined from ‘WTF::PackedAlignedPtr<T, <anonymous> >::operator bool() const [with T = JSC::SharedArrayBufferContents; long unsigned int passedAlignment = 1]’ at WTF/Headers/wtf/Packed.h:197:48, inlined from ‘WTF::RefPtr<T, <template-parameter-1-2>, <template-parameter-1-3> >::operator WTF::RefPtr<T, <template-parameter-1-2>, <template-parameter-1-3> >::UnspecifiedBoolType() const [with T = JSC::SharedArrayBufferContents; _PtrTraits = WTF::PackedPtrTraits<JSC::SharedArrayBufferContents>; _RefDerefTraits = WTF::DefaultRefDerefTraits<JSC::SharedArrayBufferContents>]’ at WTF/Headers/wtf/RefPtr.h:91:57, inlined from ‘bool JSC::ArrayBufferContents::isShared() const’ at JavaScriptCore/PrivateHeaders/JavaScriptCore/ArrayBuffer.h:84:36, inlined from ‘bool JSC::ArrayBuffer::isShared() const’ at JavaScriptCore/PrivateHeaders/JavaScriptCore/ArrayBuffer.h:202:31, inlined from ‘WTF::RefPtr<JSC::ArrayBuffer> JSC::ArrayBufferView::unsharedBuffer() const’ at JavaScriptCore/PrivateHeaders/JavaScriptCore/ArrayBufferView.h:60:9, inlined from ‘WebCore::ExceptionOr<void> WebCore::WebSocket::send(JSC::ArrayBufferView&)’ at ../../Source/WebCore/Modules/websockets/WebSocket.cpp:389:52: WTF/Headers/wtf/Packed.h:147:15: warning: ‘void* memcpy(void*, const void*, size_t)’ reading 6 bytes from a region of size 0 [-Wstringop-overread] 147 | memcpy(&value, m_storage.data(), storageSize); | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ We know it's "safe" because storageSize <= sizeof(uintptr_t), and since r278878 we now have a static_assert to guarantee that. But the compiler not-unreasonably thinks it's bad because value is not an array.
Michael Catanzaro
Comment 6 2021-06-28 08:15:31 PDT
Michael Catanzaro
Comment 7 2021-06-28 08:54:56 PDT
Comment on attachment 432395 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=432395&action=review > Source/WTF/wtf/Packed.h:149 > +IGNORE_WARNINGS_BEGIN("stringop-overread") It doesn't work. GCC is just ignoring the pragma. We might have to rewrite this code.
Michael Catanzaro
Comment 8 2021-06-30 10:57:40 PDT
Michael Catanzaro
Comment 9 2021-06-30 12:52:36 PDT
Comment on attachment 432610 [details] Patch Ugh, I made a last-minute improvement that reintroduced the -Wstringop-overread warning that this patch was intended to fix. This warning is brutal. I don't understand why the usual warning pragmas are unable to suppress it. Normally they work for all warnings except those implemented by the preprocessor (cpp)....
Michael Catanzaro
Comment 10 2021-07-29 13:13:37 PDT
We'll use -Wno-array-bounds to eliminate the -Warray-bounds warning, bug #228601. That will introduce the -Wstringop-truncation warning. The only solution I found is -Wno-stringop-truncation. So far I've tested using it globally, but since this warning does not have an excessive amount of false positives like -Warray-bounds does, I think we can safely remove WebSocket.cpp from the unified build and apply the flag only to this file.
Michael Catanzaro
Comment 11 2021-07-29 14:00:20 PDT
Michael Catanzaro
Comment 12 2021-07-29 16:29:20 PDT
Ah, I need to add WebSocket.cpp to the XCode project, because that is a thing.
Michael Catanzaro
Comment 13 2021-07-30 07:28:33 PDT
Michael Catanzaro
Comment 14 2021-07-30 07:36:11 PDT
Michael Catanzaro
Comment 15 2021-07-30 07:42:07 PDT
Michael Catanzaro
Comment 16 2021-07-30 07:42:54 PDT
(In reply to Michael Catanzaro from comment #15) > Created attachment 434624 [details] > Patch If this doesn't work, I'm going to give up on editing the XCode project, and suppress -Wstringop-overread globally instead.
Michael Catanzaro
Comment 17 2021-07-30 07:46:48 PDT
(In reply to Michael Catanzaro from comment #16) > If this doesn't work, I'm going to give up on editing the XCode project I am defeated. :/
Michael Catanzaro
Comment 18 2021-07-30 08:01:39 PDT
Maybe an Apple developer would be willing to help with removing WebSocket.cpp from the unified build? Otherwise, I will suppress -Wstringop-truncation globally when built with GCC in bug #228601. It's very frustrating that it cannot be suppressed with pragmas. :/
Michael Catanzaro
Comment 19 2021-08-05 07:52:44 PDT
(In reply to Michael Catanzaro from comment #18) > Maybe an Apple developer would be willing to help with removing > WebSocket.cpp from the unified build? Otherwise, I will suppress > -Wstringop-truncation globally when built with GCC in bug #228601. It's very > frustrating that it cannot be suppressed with pragmas. :/ Darin handled this in bug #228808. Thanks Darin!
Michael Catanzaro
Comment 20 2021-08-05 08:04:21 PDT
EWS
Comment 21 2021-08-09 08:59:35 PDT
Committed r280778 (240362@main): <https://commits.webkit.org/240362@main> All reviewed patches have been landed. Closing bug and clearing flags on attachment 434985 [details].
Michael Catanzaro
Comment 22 2021-11-11 10:42:35 PST
Reopening. When building with LTO enabled, there are more warnings here: [5489/5749] Linking CXX executable bin/TestWebKitAPI/TestWebCore /home/mcatanzaro/Projects/WebKit/Source/ThirdParty/ANGLE/src/compiler/translator/ParseContext.h:33: note: type name ‘sh::TParseContext’ should match type name ‘angle::pp::Tokenizer::Context’ 33 | class TParseContext : angle::NonCopyable | /home/mcatanzaro/Projects/WebKit/Source/ThirdParty/ANGLE/src/compiler/preprocessor/Tokenizer.h:25: note: the incompatible type is defined here 25 | struct Context | In member function ‘get’, inlined from ‘__conv_op ’ at /home/mcatanzaro/Projects/WebKit/WebKitBuild/GNOME/WTF/Headers/wtf/Packed.h:198:48, inlined from ‘__conv_op ’ at /home/mcatanzaro/Projects/WebKit/WebKitBuild/GNOME/WTF/Headers/wtf/RefPtr.h:89:57, inlined from ‘isShared’ at /home/mcatanzaro/Projects/WebKit/WebKitBuild/GNOME/JavaScriptCore/PrivateHeaders/JavaScriptCore/ArrayBuffer.h:93:36, inlined from ‘isShared’ at /home/mcatanzaro/Projects/WebKit/WebKitBuild/GNOME/JavaScriptCore/PrivateHeaders/JavaScriptCore/ArrayBuffer.h:211:31, inlined from ‘unsharedBuffer’ at /home/mcatanzaro/Projects/WebKit/WebKitBuild/GNOME/JavaScriptCore/PrivateHeaders/JavaScriptCore/ArrayBufferView.h:61:9, inlined from ‘send’ at /home/mcatanzaro/Projects/WebKit/Source/WebCore/Modules/websockets/WebSocket.cpp:386:52, inlined from ‘operator()’ at /home/mcatanzaro/Projects/WebKit/WebKitBuild/GNOME/WebCore/DerivedSources/JSWebSocket.cpp:537:5, inlined from ‘toJS’ at /home/mcatanzaro/Projects/WebKit/Source/WebCore/bindings/js/JSDOMConvertBase.h:168:18, inlined from ‘jsWebSocketPrototypeFunction_send2Body’ at /home/mcatanzaro/Projects/WebKit/WebKitBuild/GNOME/WebCore/DerivedSources/JSWebSocket.cpp:537:5, inlined from ‘jsWebSocketPrototypeFunction_sendOverloadDispatcher’ at /home/mcatanzaro/Projects/WebKit/WebKitBuild/GNOME/WebCore/DerivedSources/JSWebSocket.cpp:578:13, inlined from ‘call’ at /home/mcatanzaro/Projects/WebKit/Source/WebCore/bindings/js/JSDOMOperation.h:63:9, inlined from ‘jsWebSocketPrototypeFunction_send’ at /home/mcatanzaro/Projects/WebKit/WebKitBuild/GNOME/WebCore/DerivedSources/JSWebSocket.cpp:588:96: /home/mcatanzaro/Projects/WebKit/WebKitBuild/GNOME/WTF/Headers/wtf/Packed.h:146:15: warning: ‘__builtin_memcpy’ reading 6 bytes from a region of size 0 [-Wstringop-overread] 146 | memcpy(&value, m_storage.data(), storageSize); | ^ [5490/5749] Linking CXX shared library lib/libwebkit2gtk-4.1.so.0.1.0 /home/mcatanzaro/Projects/WebKit/Source/ThirdParty/ANGLE/src/compiler/translator/ParseContext.h:33: note: type name ‘sh::TParseContext’ should match type name ‘angle::pp::Tokenizer::Context’ 33 | class TParseContext : angle::NonCopyable | /home/mcatanzaro/Projects/WebKit/Source/ThirdParty/ANGLE/src/compiler/preprocessor/Tokenizer.h:25: note: the incompatible type is defined here 25 | struct Context | In member function ‘get’, inlined from ‘__conv_op ’ at /home/mcatanzaro/Projects/WebKit/WebKitBuild/GNOME/WTF/Headers/wtf/Packed.h:198:48, inlined from ‘__conv_op ’ at /home/mcatanzaro/Projects/WebKit/WebKitBuild/GNOME/WTF/Headers/wtf/RefPtr.h:89:57, inlined from ‘isShared’ at /home/mcatanzaro/Projects/WebKit/WebKitBuild/GNOME/JavaScriptCore/PrivateHeaders/JavaScriptCore/ArrayBuffer.h:93:36, inlined from ‘isShared’ at /home/mcatanzaro/Projects/WebKit/WebKitBuild/GNOME/JavaScriptCore/PrivateHeaders/JavaScriptCore/ArrayBuffer.h:211:31, inlined from ‘unsharedBuffer’ at /home/mcatanzaro/Projects/WebKit/WebKitBuild/GNOME/JavaScriptCore/PrivateHeaders/JavaScriptCore/ArrayBufferView.h:61:9, inlined from ‘send’ at /home/mcatanzaro/Projects/WebKit/Source/WebCore/Modules/websockets/WebSocket.cpp:386:52, inlined from ‘operator()’ at /home/mcatanzaro/Projects/WebKit/WebKitBuild/GNOME/WebCore/DerivedSources/JSWebSocket.cpp:537:5, inlined from ‘toJS’ at /home/mcatanzaro/Projects/WebKit/Source/WebCore/bindings/js/JSDOMConvertBase.h:168:18, inlined from ‘jsWebSocketPrototypeFunction_send2Body’ at /home/mcatanzaro/Projects/WebKit/WebKitBuild/GNOME/WebCore/DerivedSources/JSWebSocket.cpp:537:5, inlined from ‘jsWebSocketPrototypeFunction_sendOverloadDispatcher’ at /home/mcatanzaro/Projects/WebKit/WebKitBuild/GNOME/WebCore/DerivedSources/JSWebSocket.cpp:578:13, inlined from ‘call’ at /home/mcatanzaro/Projects/WebKit/Source/WebCore/bindings/js/JSDOMOperation.h:63:9, inlined from ‘jsWebSocketPrototypeFunction_send’ at /home/mcatanzaro/Projects/WebKit/WebKitBuild/GNOME/WebCore/DerivedSources/JSWebSocket.cpp:588:96: /home/mcatanzaro/Projects/WebKit/WebKitBuild/GNOME/WTF/Headers/wtf/Packed.h:146:15: warning: ‘memcpy’ reading 6 bytes from a region of size 0 [-Wstringop-overread] 146 | memcpy(&value, m_storage.data(), storageSize); | ^ I'm not sure if it is possible to suppress them only for affected source files because they are derived sources and would have to be somehow removed from the unified build. Might need to revert r240362 and suppress -Wstringop-overread globally when building with GCC, since this is yet another case where pragmas fail to suppress the warning.
Michael Catanzaro
Comment 23 2021-11-11 10:56:49 PST
I'm going to turn off -Wstringop-overread for all of WebKit when building with GCC 11 or newer. Note this particular instance of the warning is a false-positive because we read storageSize bytes from m_storage.data(), and m_storage.data() is guaranteed to storageSize, and m_storage is a std::array of size storageSize. So this seems is an extremely simple case, where it is obvious that GCC is wrong, but we can't use the IGNORE_WARNINGS scalpel, and therefore must resort to the sledgehammer....
Michael Catanzaro
Comment 24 2021-11-11 10:58:04 PST
(In reply to Michael Catanzaro from comment #22) > Might need to revert r240362 I meant 240362@main, which is r280778.
Darin Adler
Comment 25 2021-11-11 11:11:30 PST
In general, when we have these kinds of warning issues, I think it’s OK to first turn off the warning globally (for the particular problematic compiler, and no more) and then try to restore the warning, but without the time pressure caused by having builds failing with -Werror. Do you think that can work? Of course we are worried that eventually we’ll have many useful warnings left turned off, but the harder we work at it, the more we can restore those warnings. Meanwhile, we’ll still have a project that can build.
Michael Catanzaro
Comment 26 2021-11-11 11:18:48 PST
Note we don't use -Werror at all currently, but I'm trying to change that in bug #155047, so this does block the effort to enable it. (In reply to Darin Adler from comment #25) > In general, when we have these kinds of warning issues, I think it’s OK to > first turn off the warning globally (for the particular problematic > compiler, and no more) I have a patch to turn it off specifically for GCC 11 and newer versions. > and then try to restore the warning, but without the > time pressure caused by having builds failing with -Werror. Realistically, it will require changes in GCC. I've complained to GCC devs and we'll see what they say.
Michael Catanzaro
Comment 27 2021-11-11 11:20:38 PST
EWS
Comment 28 2021-11-11 13:09:45 PST
Committed r285652 (244150@main): <https://commits.webkit.org/244150@main> All reviewed patches have been landed. Closing bug and clearing flags on attachment 443980 [details].
Note You need to log in before you can comment on or make changes to this bug.