Changeset 165681 in webkit


Ignore:
Timestamp:
Mar 15, 2014 8:21:06 AM (10 years ago)
Author:
ddkilzer@apple.com
Message:

Fix undefined behavior in WTF::equal() in StringImpl.h for i386/x86_64
<http://webkit.org/b/130283>
<rdar://problem/16281477>

Reviewed by Geoff Garen.

  • wtf/text/StringImpl.h:

(WTF::loadUnaligned): Add template method.
(WTF::equal): Switch to using loadUnaligned<>().

Location:
trunk/Source/WTF
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WTF/ChangeLog

    r165677 r165681  
     12014-03-15  David Kilzer  <ddkilzer@apple.com>
     2
     3        Fix undefined behavior in WTF::equal() in StringImpl.h for i386/x86_64
     4        <http://webkit.org/b/130283>
     5        <rdar://problem/16281477>
     6
     7        Reviewed by Geoff Garen.
     8
     9        * wtf/text/StringImpl.h:
     10        (WTF::loadUnaligned): Add template method.
     11        (WTF::equal): Switch to using loadUnaligned<>().
     12
    1132014-03-14  Mark Rowe  <mrowe@apple.com>
    214
  • trunk/Source/WTF/wtf/text/StringImpl.h

    r165152 r165681  
    916916WTF_EXPORT_STRING_API bool equal(const StringImpl& a, const StringImpl& b);
    917917
     918template<typename T>
     919inline T loadUnaligned(const char* s)
     920{
     921    T tmp;
     922    memcpy(&tmp, s, sizeof(T));
     923    return tmp;
     924}
     925
    918926// Do comparisons 8 or 4 bytes-at-a-time on architectures where it's safe.
    919927#if CPU(X86_64) || CPU(ARM64)
    920 ALWAYS_INLINE bool equal(const LChar* a, const LChar* b, unsigned length)
     928ALWAYS_INLINE bool equal(const LChar* aLChar, const LChar* bLChar, unsigned length)
    921929{
    922930    unsigned dwordLength = length >> 3;
    923931
     932    const char* a = reinterpret_cast<const char*>(aLChar);
     933    const char* b = reinterpret_cast<const char*>(bLChar);
     934
    924935    if (dwordLength) {
    925         const uint64_t* aDWordCharacters = reinterpret_cast<const uint64_t*>(a);
    926         const uint64_t* bDWordCharacters = reinterpret_cast<const uint64_t*>(b);
    927 
    928936        for (unsigned i = 0; i != dwordLength; ++i) {
    929             if (*aDWordCharacters++ != *bDWordCharacters++)
     937            if (loadUnaligned<uint64_t>(a) != loadUnaligned<uint64_t>(b))
    930938                return false;
     939
     940            a += sizeof(uint64_t);
     941            b += sizeof(uint64_t);
    931942        }
    932 
    933         a = reinterpret_cast<const LChar*>(aDWordCharacters);
    934         b = reinterpret_cast<const LChar*>(bDWordCharacters);
    935943    }
    936944
    937945    if (length & 4) {
    938         if (*reinterpret_cast<const uint32_t*>(a) != *reinterpret_cast<const uint32_t*>(b))
     946        if (loadUnaligned<uint32_t>(a) != loadUnaligned<uint32_t>(b))
    939947            return false;
    940948
    941         a += 4;
    942         b += 4;
     949        a += sizeof(uint32_t);
     950        b += sizeof(uint32_t);
    943951    }
    944952
    945953    if (length & 2) {
    946         if (*reinterpret_cast<const uint16_t*>(a) != *reinterpret_cast<const uint16_t*>(b))
     954        if (loadUnaligned<uint16_t>(a) != loadUnaligned<uint16_t>(b))
    947955            return false;
    948956
    949         a += 2;
    950         b += 2;
    951     }
    952 
    953     if (length & 1 && (*a != *b))
     957        a += sizeof(uint16_t);
     958        b += sizeof(uint16_t);
     959    }
     960
     961    if (length & 1 && (*reinterpret_cast<const LChar*>(a) != *reinterpret_cast<const LChar*>(b)))
    954962        return false;
    955963
     
    957965}
    958966
    959 ALWAYS_INLINE bool equal(const UChar* a, const UChar* b, unsigned length)
     967ALWAYS_INLINE bool equal(const UChar* aUChar, const UChar* bUChar, unsigned length)
    960968{
    961969    unsigned dwordLength = length >> 2;
    962    
     970
     971    const char* a = reinterpret_cast<const char*>(aUChar);
     972    const char* b = reinterpret_cast<const char*>(bUChar);
     973
    963974    if (dwordLength) {
    964         const uint64_t* aDWordCharacters = reinterpret_cast<const uint64_t*>(a);
    965         const uint64_t* bDWordCharacters = reinterpret_cast<const uint64_t*>(b);
    966 
    967975        for (unsigned i = 0; i != dwordLength; ++i) {
    968             if (*aDWordCharacters++ != *bDWordCharacters++)
     976            if (loadUnaligned<uint64_t>(a) != loadUnaligned<uint64_t>(b))
    969977                return false;
     978
     979            a += sizeof(uint64_t);
     980            b += sizeof(uint64_t);
    970981        }
    971 
    972         a = reinterpret_cast<const UChar*>(aDWordCharacters);
    973         b = reinterpret_cast<const UChar*>(bDWordCharacters);
    974982    }
    975983
    976984    if (length & 2) {
    977         if (*reinterpret_cast<const uint32_t*>(a) != *reinterpret_cast<const uint32_t*>(b))
     985        if (loadUnaligned<uint32_t>(a) != loadUnaligned<uint32_t>(b))
    978986            return false;
    979987
    980         a += 2;
    981         b += 2;
    982     }
    983 
    984     if (length & 1 && (*a != *b))
     988        a += sizeof(uint32_t);
     989        b += sizeof(uint32_t);
     990    }
     991
     992    if (length & 1 && (*reinterpret_cast<const UChar*>(a) != *reinterpret_cast<const UChar*>(b)))
    985993        return false;
    986994
     
    988996}
    989997#elif CPU(X86)
    990 ALWAYS_INLINE bool equal(const LChar* a, const LChar* b, unsigned length)
    991 {
    992     const uint32_t* aCharacters = reinterpret_cast<const uint32_t*>(a);
    993     const uint32_t* bCharacters = reinterpret_cast<const uint32_t*>(b);
     998ALWAYS_INLINE bool equal(const LChar* aLChar, const LChar* bLChar, unsigned length)
     999{
     1000    const char* a = reinterpret_cast<const char*>(aLChar);
     1001    const char* b = reinterpret_cast<const char*>(bLChar);
    9941002
    9951003    unsigned wordLength = length >> 2;
    9961004    for (unsigned i = 0; i != wordLength; ++i) {
    997         if (*aCharacters++ != *bCharacters++)
     1005        if (loadUnaligned<uint32_t>(a) != loadUnaligned<uint32_t>(b))
    9981006            return false;
     1007        a += sizeof(uint32_t);
     1008        b += sizeof(uint32_t);
    9991009    }
    10001010
     
    10021012
    10031013    if (length) {
    1004         const LChar* aRemainder = reinterpret_cast<const LChar*>(aCharacters);
    1005         const LChar* bRemainder = reinterpret_cast<const LChar*>(bCharacters);
    1006        
     1014        const LChar* aRemainder = reinterpret_cast<const LChar*>(a);
     1015        const LChar* bRemainder = reinterpret_cast<const LChar*>(b);
     1016
    10071017        for (unsigned i = 0; i <  length; ++i) {
    10081018            if (aRemainder[i] != bRemainder[i])
     
    10141024}
    10151025
    1016 ALWAYS_INLINE bool equal(const UChar* a, const UChar* b, unsigned length)
    1017 {
    1018     const uint32_t* aCharacters = reinterpret_cast<const uint32_t*>(a);
    1019     const uint32_t* bCharacters = reinterpret_cast<const uint32_t*>(b);
    1020    
     1026ALWAYS_INLINE bool equal(const UChar* aUChar, const UChar* bUChar, unsigned length)
     1027{
     1028    const char* a = reinterpret_cast<const char*>(aUChar);
     1029    const char* b = reinterpret_cast<const char*>(bUChar);
     1030
    10211031    unsigned wordLength = length >> 1;
    10221032    for (unsigned i = 0; i != wordLength; ++i) {
    1023         if (*aCharacters++ != *bCharacters++)
     1033        if (loadUnaligned<uint32_t>(a) != loadUnaligned<uint32_t>(b))
    10241034            return false;
    1025     }
    1026    
    1027     if (length & 1 && *reinterpret_cast<const UChar*>(aCharacters) != *reinterpret_cast<const UChar*>(bCharacters))
     1035        a += sizeof(uint32_t);
     1036        b += sizeof(uint32_t);
     1037    }
     1038
     1039    if (length & 1 && *reinterpret_cast<const UChar*>(a) != *reinterpret_cast<const UChar*>(b))
    10281040        return false;
    1029    
     1041
    10301042    return true;
    10311043}
Note: See TracChangeset for help on using the changeset viewer.