RESOLVED FIXED Bug 47594
Misaligned memory access in CloneDeserializer on ARM (<v6)
https://bugs.webkit.org/show_bug.cgi?id=47594
Summary Misaligned memory access in CloneDeserializer on ARM (<v6)
Yong Li
Reported 2010-10-13 08:44:31 PDT
Bug 45301 fixes the warning, but the problem still exists. On ARM (<v6), CloneDeserializer::readLittleEndian and readString can result misaligned memory access. #if ASSUME_LITTLE_ENDIAN template <typename T> static bool readLittleEndian(const uint8_t*& ptr, const uint8_t* end, T& value) { if (ptr > end – sizeof(value)) return false; if (sizeof(T) == 1) value = *ptr++; else { value = *reinterpret_cast_ptr<const T*>(ptr); // here I think we should do memcpy(&value, ptr, sizeof(value)) ptr += sizeof(T); } return true; }
Attachments
the patch (2.30 KB, patch)
2010-10-13 08:49 PDT, Yong Li
no flags
The patch (no test added because...) (2.41 KB, patch)
2010-10-13 09:43 PDT, Yong Li
oliver: review-
updated (1.99 KB, patch)
2010-10-13 10:23 PDT, Yong Li
no flags
Yong Li
Comment 1 2010-10-13 08:49:30 PDT
Created attachment 70612 [details] the patch trying to get a test case
Yong Li
Comment 2 2010-10-13 09:43:59 PDT
Created attachment 70617 [details] The patch (no test added because...) no new test is added because the crash can be reproduced by loading some existing tests like: LayoutTests/fast/events/message-channel-gc-4.html
Oliver Hunt
Comment 3 2010-10-13 10:08:45 PDT
Comment on attachment 70617 [details] The patch (no test added because...) View in context: https://bugs.webkit.org/attachment.cgi?id=70617&action=review r- due to the issues I noted. The duplicate string copy is the biggest concern. > WebCore/bindings/js/SerializedScriptValue.cpp:824 > + if (reinterpret_cast<unsigned>(ptr) & (sizeof(T) - 1)) when casting a pointer to an integer type you should always use uintptr_t or intptr_t (in this case you want uintptr_t) > WebCore/bindings/js/SerializedScriptValue.cpp:828 > +#else Honestly I think that given the likelihood of an unaligned read we should probably just drop the alignment check on armv5 or lower and always do a memcpy > WebCore/bindings/js/SerializedScriptValue.cpp:924 > + // Use 32-character-long inline buffer as a fast path for small strings. > + Vector<UChar, 32> alignedBuffer(length); > + memcpy(alignedBuffer.data(), ptr, length * sizeof(UChar)); > + str = UString(alignedBuffer.data(), length); This results in multiple copies, rather than str = UString(....) you should do str = UString::adopt(alignedBuffer);
Yong Li
Comment 4 2010-10-13 10:11:16 PDT
(In reply to comment #3) > (From update of attachment 70617 [details]) > View in context: https://bugs.webkit.org/attachment.cgi?id=70617&action=review > > r- due to the issues I noted. The duplicate string copy is the biggest concern. > > > WebCore/bindings/js/SerializedScriptValue.cpp:824 > > + if (reinterpret_cast<unsigned>(ptr) & (sizeof(T) - 1)) > > when casting a pointer to an integer type you should always use uintptr_t or intptr_t (in this case you want uintptr_t) > > > WebCore/bindings/js/SerializedScriptValue.cpp:828 > > +#else > > Honestly I think that given the likelihood of an unaligned read we should probably just drop the alignment check on armv5 or lower and always do a memcpy > > > WebCore/bindings/js/SerializedScriptValue.cpp:924 > > + // Use 32-character-long inline buffer as a fast path for small strings. > > + Vector<UChar, 32> alignedBuffer(length); > > + memcpy(alignedBuffer.data(), ptr, length * sizeof(UChar)); > > + str = UString(alignedBuffer.data(), length); > > This results in multiple copies, rather than str = UString(....) you should do > str = UString::adopt(alignedBuffer); Thanks a lot. I'll update the patch soon
Yong Li
Comment 5 2010-10-13 10:23:06 PDT
Created attachment 70621 [details] updated 1. use uintptr_t to cast pointer to integer 2. use UString::adopt to avoid duplicate copy 3. remove the aligned code paths
Oliver Hunt
Comment 6 2010-10-13 10:39:33 PDT
Comment on attachment 70621 [details] updated Nice
WebKit Commit Bot
Comment 7 2010-10-13 12:22:05 PDT
Comment on attachment 70621 [details] updated Clearing flags on attachment: 70621 Committed r69682: <http://trac.webkit.org/changeset/69682>
WebKit Commit Bot
Comment 8 2010-10-13 12:22:12 PDT
All reviewed patches have been landed. Closing bug.
WebKit Review Bot
Comment 9 2010-10-13 13:15:04 PDT
http://trac.webkit.org/changeset/69682 might have broken GTK Linux 64-bit Debug
Gabor Loki
Comment 10 2010-10-14 00:48:12 PDT
Hmm, it looks like I missed that alignment difference when I fixed that warnings. I assumed the buffer of CloneDeserializer is allocated in a natural way, but the m_data of SerializedScriptValue is allocated as a char vector. Although the fix is good, you should consider the MIPS uses natural alignment as well. Well, MIPS has unaligned load/store instruction, but the GCC also warns on unaligned data access (see deepak's comments at bug 43963). My suggestion is to create a WTF_CPU_NATURAL_ALIGNMENT_IS_NEEDED macro in Platform.h, and set it for WTF_CPU_ARMV5_OR_LOWER and WTF_CPU_MIPS as well. So, we can use CPU(NATURAL_ALIGNMENT_IS_NEEDED) instead of current CPU(ARMV5_OR_LOWER) check. At first of all it would be nice someone who has MIPS to confirm this warning.
Yong Li
Comment 11 2010-10-14 07:55:49 PDT
(In reply to comment #10) > Hmm, it looks like I missed that alignment difference when I fixed that warnings. I assumed the buffer of CloneDeserializer is allocated in a natural way, but the m_data of SerializedScriptValue is allocated as a char vector. > Although the fix is good, you should consider the MIPS uses natural alignment as well. Well, MIPS has unaligned load/store instruction, but the GCC also warns on unaligned data access (see deepak's comments at bug 43963). > My suggestion is to create a WTF_CPU_NATURAL_ALIGNMENT_IS_NEEDED macro in Platform.h, and set it for WTF_CPU_ARMV5_OR_LOWER and WTF_CPU_MIPS as well. So, we can use CPU(NATURAL_ALIGNMENT_IS_NEEDED) instead of current CPU(ARMV5_OR_LOWER) check. > At first of all it would be nice someone who has MIPS to confirm this warning. CPU(NATURAL_ALIGNMENT_IS_NEEDED) is good idea. I used CPU(ARMV5_OR_LOWER) because I see it is also being used somewhere else for alignment isue. About the warning, probably we should find a better way to suppress it. reinterpret_cast_ptr is different from reinterpret_cast only for #if CPU(ARM) && COMPILER(GCC), and it asserts that the pointer is already aligned. ASSERT(isPointerTypeAlignmentOkay(reinterpret_cast<TypePtr>(ptr))); So even on ARMv6, the debug build will throw an assertion, which is also annoying.
Kimmo Kinnunen
Comment 12 2010-10-31 23:36:32 PDT
> CPU(NATURAL_ALIGNMENT_IS_NEEDED) is good idea. I used CPU(ARMV5_OR_LOWER) because I see it is also being used somewhere else for alignment isue. It may be that CPU(NATURAL_ALIGNMENT_IS_NEEDED) is not fine-grained enough. Long longs seem to cause crashes on ARMv7 too (at least on some platform+toolchain combination). Related bug: http://bugs.webkit.org/show_bug.cgi?id=48742
Note You need to log in before you can comment on or make changes to this bug.