Bug 130283 - Fix undefined behavior in WTF::equal() in StringImpl.h for i386/x86_64
Summary: Fix undefined behavior in WTF::equal() in StringImpl.h for i386/x86_64
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Web Template Framework (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: David Kilzer (:ddkilzer)
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2014-03-14 20:31 PDT by David Kilzer (:ddkilzer)
Modified: 2014-03-16 12:26 PDT (History)
10 users (show)

See Also:


Attachments
i386 assembly before patch (3.02 KB, text/plain)
2014-03-14 20:44 PDT, David Kilzer (:ddkilzer)
no flags Details
i386 assembly with patch (3.02 KB, text/plain)
2014-03-14 20:45 PDT, David Kilzer (:ddkilzer)
no flags Details
x86_64 assembly before patch (4.37 KB, text/plain)
2014-03-14 20:46 PDT, David Kilzer (:ddkilzer)
no flags Details
x86_64 assembly with patch (4.37 KB, text/plain)
2014-03-14 20:46 PDT, David Kilzer (:ddkilzer)
no flags Details
Patch v1 (7.14 KB, patch)
2014-03-14 21:15 PDT, David Kilzer (:ddkilzer)
ggaren: review+
ggaren: commit-queue-
Details | Formatted Diff | Diff
Patch for follow-up issue (1.28 KB, patch)
2014-03-16 11:46 PDT, David Kilzer (:ddkilzer)
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description David Kilzer (:ddkilzer) 2014-03-14 20:31:12 PDT
When compiling WebKit with -fcatch-undefined-behavior (UBSan), Safari crashes on launch due to undefined behavior in WTF::equal() due to casting unaligned const char* bytes to unit64_t, uint32_t, etc.

We can fix the unaligned access using memcpy, and clang will still optimize the code the exact same way (without calling memcpy for short lengths).
Comment 1 David Kilzer (:ddkilzer) 2014-03-14 20:31:29 PDT
<rdar://problem/16281477>
Comment 2 David Kilzer (:ddkilzer) 2014-03-14 20:44:55 PDT
Created attachment 226798 [details]
i386 assembly before patch
Comment 3 David Kilzer (:ddkilzer) 2014-03-14 20:45:33 PDT
Created attachment 226799 [details]
i386 assembly with patch
Comment 4 David Kilzer (:ddkilzer) 2014-03-14 20:46:13 PDT
Created attachment 226800 [details]
x86_64 assembly before patch
Comment 5 David Kilzer (:ddkilzer) 2014-03-14 20:46:50 PDT
Created attachment 226801 [details]
x86_64 assembly with patch
Comment 6 David Kilzer (:ddkilzer) 2014-03-14 21:15:38 PDT
Created attachment 226803 [details]
Patch v1
Comment 7 Geoffrey Garen 2014-03-15 00:51:22 PDT
Comment on attachment 226803 [details]
Patch v1

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

r=me

> Source/WTF/wtf/text/StringImpl.h:919
> +inline T load_unaligned(const char* s)

"loadUnaligned"
Comment 8 David Kilzer (:ddkilzer) 2014-03-15 08:21:52 PDT
Committed r165681: <http://trac.webkit.org/changeset/165681>
Comment 9 Darin Adler 2014-03-15 14:32:24 PDT
Comment on attachment 226803 [details]
Patch v1

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

> Source/WTF/wtf/text/StringImpl.h:926
>  // Do comparisons 8 or 4 bytes-at-a-time on architectures where it's safe.

I think that this patch renders this comment incorrect. We compile the version that does comparisons multiple bytes at a time on configurations where we believe it will compile to more efficient code than the baseline. Now that we are writing the efficient code in terms of memcpy, I think it may be “safe” everywhere. I’m not even sure the conditional is right anymore, since the code now depends on both the architecture and the compiler. For example, this may have made Windows X86_64 significantly slower.
Comment 10 David Kilzer (:ddkilzer) 2014-03-15 21:38:34 PDT
(In reply to comment #9)
> (From update of attachment 226803 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=226803&action=review
> 
> > Source/WTF/wtf/text/StringImpl.h:926
> >  // Do comparisons 8 or 4 bytes-at-a-time on architectures where it's safe.
> 
> I think that this patch renders this comment incorrect. We compile the version that does comparisons multiple bytes at a time on configurations where we believe it will compile to more efficient code than the baseline. Now that we are writing the efficient code in terms of memcpy, I think it may be “safe” everywhere. I’m not even sure the conditional is right anymore, since the code now depends on both the architecture and the compiler. For example, this may have made Windows X86_64 significantly slower.

Can someone attach assembly output for WTF::stringImplContentEqual() (__ZN3WTFL22stringImplContentEqualERKNS_10StringImplES2_) for Windows?  It would likely be sufficient to check if Visual C++ is smart enough to optimize out the memcpy calls from the function.

Some options are:

1. Add a check for the clang compiler for the conforming implementation, and (optionally) add back the non-conforming ones for other compilers on the same architectures.
2. Back out this patch, then go with Darin's suggestion in Radar to add some kind of macro to make sure it's possible to use the slower memcmp() methods when compiling with -fcatch-undefined-behavior.

I would prefer #1, although it bloats the code a bit more.
Comment 11 Darin Adler 2014-03-16 00:56:25 PDT
(In reply to comment #10)
> I would prefer #1, although it bloats the code a bit more.

I strongly prefer #1.
Comment 12 David Kilzer (:ddkilzer) 2014-03-16 11:27:51 PDT
(In reply to comment #11)
> (In reply to comment #10)
> > I would prefer #1, although it bloats the code a bit more.
> 
> I strongly prefer #1.

I thought of a more targeted fix this morning:

 template<typename T>
 inline T loadUnaligned(const char* s)
 {
+#if COMPILER(CLANG)
     T tmp;
     memcpy(&tmp, s, sizeof(T));
     return tmp;
+#else
+    // This may result in undefined behavior due to an unaligned access.
+    return *reinterpret_cast<const T*>(s);
+#endif
 }
Comment 13 David Kilzer (:ddkilzer) 2014-03-16 11:39:59 PDT
Re-opening for follow-up fix.
Comment 14 David Kilzer (:ddkilzer) 2014-03-16 11:46:27 PDT
Created attachment 226849 [details]
Patch for follow-up issue

Patch to restore behavior prior to <http://trac.webkit.org/r165681> for non-clang compilers.
Comment 15 WebKit Commit Bot 2014-03-16 12:26:25 PDT
Comment on attachment 226849 [details]
Patch for follow-up issue

Clearing flags on attachment: 226849

Committed r165706: <http://trac.webkit.org/changeset/165706>
Comment 16 WebKit Commit Bot 2014-03-16 12:26:30 PDT
All reviewed patches have been landed.  Closing bug.