Ignore:
Timestamp:
Aug 16, 2018, 2:41:36 AM (7 years ago)
Author:
[email protected]
Message:

[YARR] Align allocation size in BumpPointerAllocator with sizeof(void*)
https://bugs.webkit.org/show_bug.cgi?id=188571

Reviewed by Saam Barati.

UBSan finds YarrInterpreter performs misaligned accesses. This is because YarrInterpreter
allocates DisjunctionContext and ParenthesesDisjunctionContext from BumpPointerAllocator
without considering alignment of them. This patch adds DisjunctionContext::allocationSize
and ParenthesesDisjunctionContext::allocationSize to calculate allocation sizes for them.
The size is always rounded to sizeof(void*) so that these classes are always allocated
with sizeof(void*) alignment. We also ensure the alignments of both classes are less
than or equal to sizeof(void*) by static_assert.

  • yarr/YarrInterpreter.cpp:

(JSC::Yarr::Interpreter::DisjunctionContext::allocationSize):
(JSC::Yarr::Interpreter::allocDisjunctionContext):
(JSC::Yarr::Interpreter::ParenthesesDisjunctionContext::ParenthesesDisjunctionContext):
(JSC::Yarr::Interpreter::ParenthesesDisjunctionContext::getDisjunctionContext):
(JSC::Yarr::Interpreter::ParenthesesDisjunctionContext::allocationSize):
(JSC::Yarr::Interpreter::allocParenthesesDisjunctionContext):
(JSC::Yarr::Interpreter::Interpreter):
(JSC::Yarr::Interpreter::DisjunctionContext::DisjunctionContext): Deleted.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/yarr/YarrInterpreter.cpp

    r232718 r234916  
    3333#include "YarrCanonicalize.h"
    3434#include <wtf/BumpPointerAllocator.h>
     35#include <wtf/CheckedArithmetic.h>
    3536#include <wtf/DataLog.h>
    3637#include <wtf/text/CString.h>
     
    6869    struct DisjunctionContext
    6970    {
    70         DisjunctionContext()
    71             : term(0)
    72         {
    73         }
     71        DisjunctionContext() = default;
    7472
    7573        void* operator new(size_t, void* where)
     
    7876        }
    7977
    80         int term;
     78        static size_t allocationSize(unsigned numberOfFrames)
     79        {
     80            static_assert(alignof(DisjunctionContext) <= sizeof(void*), "");
     81            size_t rawSize = (sizeof(DisjunctionContext) - sizeof(uintptr_t) + Checked<size_t>(numberOfFrames) * sizeof(uintptr_t)).unsafeGet();
     82            size_t roundedSize = roundUpToMultipleOf<sizeof(void*)>(rawSize);
     83            RELEASE_ASSERT(roundedSize >= rawSize);
     84            return roundedSize;
     85        }
     86
     87        int term { 0 };
    8188        unsigned matchBegin;
    8289        unsigned matchEnd;
     
    8693    DisjunctionContext* allocDisjunctionContext(ByteDisjunction* disjunction)
    8794    {
    88         size_t size = sizeof(DisjunctionContext) - sizeof(uintptr_t) + disjunction->m_frameSize * sizeof(uintptr_t);
     95        size_t size = DisjunctionContext::allocationSize(disjunction->m_frameSize);
    8996        allocatorPool = allocatorPool->ensureCapacity(size);
    9097        RELEASE_ASSERT(allocatorPool);
     
    100107    {
    101108        ParenthesesDisjunctionContext(unsigned* output, ByteTerm& term)
    102             : next(0)
    103109        {
    104110            unsigned firstSubpatternId = term.atom.subpatternId;
     
    126132        DisjunctionContext* getDisjunctionContext(ByteTerm& term)
    127133        {
    128             return reinterpret_cast<DisjunctionContext*>(&(subpatternBackup[term.atom.parenthesesDisjunction->m_numSubpatterns << 1]));
    129         }
    130 
    131         ParenthesesDisjunctionContext* next;
     134            return bitwise_cast<DisjunctionContext*>(bitwise_cast<uintptr_t>(this) + allocationSize(term.atom.parenthesesDisjunction->m_numSubpatterns));
     135        }
     136
     137        static size_t allocationSize(unsigned numberOfSubpatterns)
     138        {
     139            static_assert(alignof(ParenthesesDisjunctionContext) <= sizeof(void*), "");
     140            size_t rawSize = (sizeof(ParenthesesDisjunctionContext) - sizeof(unsigned) + (Checked<size_t>(numberOfSubpatterns) * 2U) * sizeof(unsigned)).unsafeGet();
     141            size_t roundedSize = roundUpToMultipleOf<sizeof(void*)>(rawSize);
     142            RELEASE_ASSERT(roundedSize >= rawSize);
     143            return roundedSize;
     144        }
     145
     146        ParenthesesDisjunctionContext* next { nullptr };
    132147        unsigned subpatternBackup[1];
    133148    };
     
    135150    ParenthesesDisjunctionContext* allocParenthesesDisjunctionContext(ByteDisjunction* disjunction, unsigned* output, ByteTerm& term)
    136151    {
    137         size_t size = sizeof(ParenthesesDisjunctionContext) - sizeof(unsigned) + (term.atom.parenthesesDisjunction->m_numSubpatterns << 1) * sizeof(unsigned) + sizeof(DisjunctionContext) - sizeof(uintptr_t) + static_cast<size_t>(disjunction->m_frameSize) * sizeof(uintptr_t);
     152        size_t size = (Checked<size_t>(ParenthesesDisjunctionContext::allocationSize(term.atom.parenthesesDisjunction->m_numSubpatterns)) + DisjunctionContext::allocationSize(disjunction->m_frameSize)).unsafeGet();
    138153        allocatorPool = allocatorPool->ensureCapacity(size);
    139154        RELEASE_ASSERT(allocatorPool);
     
    16311646        , output(output)
    16321647        , input(input, start, length, pattern->unicode())
    1633         , allocatorPool(0)
    16341648        , startOffset(start)
    16351649        , remainingMatchCount(matchLimit)
     
    16421656    unsigned* output;
    16431657    InputStream input;
    1644     BumpPointerPool* allocatorPool;
     1658    BumpPointerPool* allocatorPool { nullptr };
    16451659    unsigned startOffset;
    16461660    unsigned remainingMatchCount;
Note: See TracChangeset for help on using the changeset viewer.