Changeset 227998 in webkit


Ignore:
Timestamp:
Feb 1, 2018 11:30:30 PM (6 years ago)
Author:
mark.lam@apple.com
Message:

Fix broken bounds check in FTL's compileGetMyArgumentByVal().
https://bugs.webkit.org/show_bug.cgi?id=182419
<rdar://problem/37044945>

Reviewed by Saam Barati.

JSTests:

  • stress/regress-182419.js: Added.

Source/JavaScriptCore:

In compileGetMyArgumentByVal(), it computes:

limit = m_out.sub(limit, m_out.constInt32(m_node->numberOfArgumentsToSkip()));
...
LValue isOutOfBounds = m_out.aboveOrEqual(originalIndex, limit);

where the original "limit" is the number of arguments passed in by the caller.
If the original limit is less than numberOfArgumentsToSkip, the resultant limit
will be a large unsigned number. As a result, this will defeat the bounds check
that follows it.

Note: later on in compileGetMyArgumentByVal(), we have to adjust adjust the index
value by adding numberOfArgumentsToSkip to it, in order to determine the actual
entry in the arguments array to get.

The fix is to just add numberOfArgumentsToSkip to index upfront (instead of
subtracting it from limit), and doing an overflow speculation check on that
addition before doing the bounds check.

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileGetMyArgumentByVal):

Location:
trunk
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r227994 r227998  
     12018-02-01  Mark Lam  <mark.lam@apple.com>
     2
     3        Fix broken bounds check in FTL's compileGetMyArgumentByVal().
     4        https://bugs.webkit.org/show_bug.cgi?id=182419
     5        <rdar://problem/37044945>
     6
     7        Reviewed by Saam Barati.
     8
     9        * stress/regress-182419.js: Added.
     10
    1112018-02-01  Keith Miller  <keith_miller@apple.com>
    212
  • trunk/Source/JavaScriptCore/ChangeLog

    r227994 r227998  
     12018-02-01  Mark Lam  <mark.lam@apple.com>
     2
     3        Fix broken bounds check in FTL's compileGetMyArgumentByVal().
     4        https://bugs.webkit.org/show_bug.cgi?id=182419
     5        <rdar://problem/37044945>
     6
     7        Reviewed by Saam Barati.
     8
     9        In compileGetMyArgumentByVal(), it computes:
     10            limit = m_out.sub(limit, m_out.constInt32(m_node->numberOfArgumentsToSkip()));
     11            ...
     12            LValue isOutOfBounds = m_out.aboveOrEqual(originalIndex, limit);
     13
     14        where the original "limit" is the number of arguments passed in by the caller.
     15        If the original limit is less than numberOfArgumentsToSkip, the resultant limit
     16        will be a large unsigned number.  As a result, this will defeat the bounds check
     17        that follows it.
     18
     19        Note: later on in compileGetMyArgumentByVal(), we have to adjust adjust the index
     20        value by adding numberOfArgumentsToSkip to it, in order to determine the actual
     21        entry in the arguments array to get.
     22
     23        The fix is to just add numberOfArgumentsToSkip to index upfront (instead of
     24        subtracting it from limit), and doing an overflow speculation check on that
     25        addition before doing the bounds check.
     26
     27        * ftl/FTLLowerDFGToB3.cpp:
     28        (JSC::FTL::DFG::LowerDFGToB3::compileGetMyArgumentByVal):
     29
    1302018-02-01  Keith Miller  <keith_miller@apple.com>
    231
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r227874 r227998  
    40104010        LValue originalIndex = lowInt32(m_node->child2());
    40114011       
    4012         LValue originalLimit;
     4012        LValue numberOfArgsIncludingThis;
    40134013        if (inlineCallFrame && !inlineCallFrame->isVarargs())
    4014             originalLimit = m_out.constInt32(inlineCallFrame->argumentCountIncludingThis);
     4014            numberOfArgsIncludingThis = m_out.constInt32(inlineCallFrame->argumentCountIncludingThis);
    40154015        else {
    40164016            VirtualRegister argumentCountRegister = AssemblyHelpers::argumentCount(inlineCallFrame);
    4017             originalLimit = m_out.load32(payloadFor(argumentCountRegister));
    4018         }
    4019        
    4020         LValue limit = m_out.sub(originalLimit, m_out.int32One);
    4021        
    4022         if (m_node->numberOfArgumentsToSkip())
    4023             limit = m_out.sub(limit, m_out.constInt32(m_node->numberOfArgumentsToSkip()));
    4024        
    4025         LValue isOutOfBounds = m_out.aboveOrEqual(originalIndex, limit);
     4017            numberOfArgsIncludingThis = m_out.load32(payloadFor(argumentCountRegister));
     4018        }
     4019       
     4020        LValue numberOfArgs = m_out.sub(numberOfArgsIncludingThis, m_out.int32One);
     4021        LValue indexToCheck = originalIndex;
     4022        if (m_node->numberOfArgumentsToSkip()) {
     4023            CheckValue* check = m_out.speculateAdd(indexToCheck, m_out.constInt32(m_node->numberOfArgumentsToSkip()));
     4024            blessSpeculation(check, Overflow, noValue(), nullptr, m_origin);
     4025            indexToCheck = check;
     4026        }
     4027
     4028        LValue isOutOfBounds = m_out.aboveOrEqual(indexToCheck, numberOfArgs);
    40264029        LBasicBlock continuation = nullptr;
    40274030        LBasicBlock lastNext = nullptr;
     
    40364039            lastNext = m_out.appendTo(normalCase, continuation);
    40374040        } else
    4038             speculate(OutOfBounds, noValue(), 0, isOutOfBounds);
    4039        
    4040         LValue index = originalIndex;
    4041         if (m_node->numberOfArgumentsToSkip())
    4042             index = m_out.add(index, m_out.constInt32(m_node->numberOfArgumentsToSkip()));
    4043        
    4044         index = m_out.add(index, m_out.int32One);
    4045        
     4041            speculate(OutOfBounds, noValue(), nullptr, isOutOfBounds);
     4042       
     4043        LValue index = m_out.add(indexToCheck, m_out.int32One);
     4044
    40464045        TypedPointer base;
    40474046        if (inlineCallFrame) {
     
    40564055                base.value(), m_out.zeroExt(index, pointerType()), ScaleEight);
    40574056            result = m_out.load64(TypedPointer(m_heaps.variables.atAnyIndex(), pointer));
    4058             result = preciseIndexMask32(result, originalIndex, limit);
     4057            result = preciseIndexMask32(result, indexToCheck, numberOfArgs);
    40594058        } else
    40604059            result = m_out.constInt64(JSValue::encode(jsUndefined()));
Note: See TracChangeset for help on using the changeset viewer.