Ignore:
Timestamp:
Mar 11, 2015, 2:03:24 PM (10 years ago)
Author:
[email protected]
Message:

Calling super() in a base class results in a crash
https://bugs.webkit.org/show_bug.cgi?id=142563

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

The bug was caused by BytecodeGenerator trying to generate "super" expression inside the constructor of a base class.
Disallow that by keeping track of whether "super" has been used in the current scope or not (needsSuperBinding flag)
and then throwing a syntax error in parseFunctionInfo if it was used and the current scope wasn't the constructor of
a derived class.

  • parser/Parser.cpp:

(JSC::Parser<LexerType>::parseFunctionInfo): Don't allow super() or super.foo outside the constructor of a derived class.
(JSC::Parser<LexerType>::parseClass): Pass in the constructor kind to parseGetterSetter.
(JSC::Parser<LexerType>::parseGetterSetter): Ditto to parseFunctionInfo.
(JSC::Parser<LexerType>::parseMemberExpression): Set needsSuperBinding flag true on the containing scope.

  • parser/Parser.h:

(JSC::Scope::Scope):
(JSC::Scope::needsSuperBinding): Added.
(JSC::Scope::setNeedsSuperBinding): Added.

LayoutTests:

Added more test cases to an existing test.

  • js/class-syntax-super-expected.txt:
  • js/script-tests/class-syntax-super.js:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/parser/Parser.cpp

    r181293 r181404  
    13781378    }
    13791379    if (functionScope->hasDirectSuper()) {
    1380         bool nameIsConstructor = info.name && *info.name == m_vm->propertyNames->constructor;
    1381         semanticFailIfTrue(mode != MethodMode || !nameIsConstructor, "Cannot call super() outside of a class constructor");
    1382     }
     1380        bool isClassConstructor = mode == MethodMode && info.name && *info.name == m_vm->propertyNames->constructor;
     1381        semanticFailIfTrue(!isClassConstructor, "Cannot call super() outside of a class constructor");
     1382        semanticFailIfTrue(constructorKind == ConstructorKind::Base, "Cannot call super() in a base class constructor");
     1383    }
     1384    if (functionScope->needsSuperBinding())
     1385        semanticFailIfTrue(constructorKind == ConstructorKind::Base, "super can only be used in a method of a derived class");
     1386
    13831387    info.closeBraceOffset = m_token.m_data.offset;
    13841388    unsigned closeBraceLine = m_token.m_data.line;
     
    15041508            semanticFailIfTrue(isStaticMethod, "Cannot declare a static", stringForFunctionMode(isGetter ? GetterMode : SetterMode));
    15051509            nextExpectIdentifier(LexerFlagsIgnoreReservedWords);
    1506             property = parseGetterSetter(context, alwaysStrictInsideClass, isGetter ? PropertyNode::Getter : PropertyNode::Setter, methodStart, SuperBinding::Needed);
     1510            property = parseGetterSetter(context, alwaysStrictInsideClass, isGetter ? PropertyNode::Getter : PropertyNode::Setter, methodStart, constructorKind, SuperBinding::Needed);
    15071511            failIfFalse(property, "Cannot parse this method");
    15081512        } else {
     
    20192023
    20202024template <typename LexerType>
    2021 template <class TreeBuilder> TreeProperty Parser<LexerType>::parseGetterSetter(TreeBuilder& context, bool strict, PropertyNode::Type type, unsigned getterOrSetterStartOffset, SuperBinding superBinding)
     2025template <class TreeBuilder> TreeProperty Parser<LexerType>::parseGetterSetter(TreeBuilder& context, bool strict, PropertyNode::Type type, unsigned getterOrSetterStartOffset,
     2026    ConstructorKind constructorKind, SuperBinding superBinding)
    20222027{
    20232028    const Identifier* stringPropertyName = 0;
     
    20342039    if (type == PropertyNode::Getter) {
    20352040        failIfFalse(match(OPENPAREN), "Expected a parameter list for getter definition");
    2036         failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, GetterMode, false, ConstructorKind::Base, info)), "Cannot parse getter definition");
     2041        failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, GetterMode, false, constructorKind, info)), "Cannot parse getter definition");
    20372042    } else {
    20382043        failIfFalse(match(OPENPAREN), "Expected a parameter list for setter definition");
    2039         failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SetterMode, false, ConstructorKind::Base, info)), "Cannot parse setter definition");
     2044        failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SetterMode, false, constructorKind, info)), "Cannot parse setter definition");
    20402045    }
    20412046    if (stringPropertyName)
     
    23852390        base = context.superExpr(location);
    23862391        next();
     2392        currentScope()->setNeedsSuperBinding();
    23872393    } else
    23882394        base = parsePrimaryExpression(context);
Note: See TracChangeset for help on using the changeset viewer.