Changeset 202460 in webkit


Ignore:
Timestamp:
Jun 24, 2016 4:34:45 PM (8 years ago)
Author:
mark.lam@apple.com
Message:

[JSC] Error prototypes are called on remote scripts.
https://bugs.webkit.org/show_bug.cgi?id=52192

Reviewed by Keith Miller.

Source/JavaScriptCore:

Added a sanitizedToString() to the Error instance object so that it can be used
to get an error string without invoking getters and proxies.

  • runtime/ErrorInstance.cpp:

(JSC::ErrorInstance::finishCreation):
(JSC::ErrorInstance::sanitizedToString):

  • runtime/ErrorInstance.h:

(JSC::ErrorInstance::createStructure):
(JSC::ErrorInstance::runtimeTypeForCause):
(JSC::ErrorInstance::clearRuntimeTypeForCause):

Source/WebCore:

Test: http/tests/security/regress-52192.html

Parsing errors are reported to the main script's window.onerror function. AFAIK,
both Chrome and Firefox have the error reporting mechanism use an internal
sanitized version of Error.prototype.toString() that will not invoke any getters
or proxies instead.

This patch fixes this issue by matching Chrome and Firefox's behavior.

Note: we did not choose to make error objects and prototypes read-only because
that was observed to have broken the web.
See https://bugs.chromium.org/p/chromium/issues/detail?id=69187#c73

Credit for reporting this issue goes to Daniel Divricean (http://divricean.ro).

  • bindings/js/JSDOMBinding.cpp:

(WebCore::reportException):

  • ForwardingHeaders/runtime/ErrorInstance.h: Added.

LayoutTests:

The added test will test the following combinations of factors:

  1. Explicitly throwing an error of each of the types of JS errors i.e. Error, EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError.
  2. Validating that the error received in window.onerror does not leak any info.
  3. Validating that the 'name' and 'toString' getters set on the error prototype object does not get invoked for creating the error message to be passed to window.error.
  • http/tests/security/regress-52192-expected.txt: Added.
  • http/tests/security/regress-52192.html: Added.
  • http/tests/security/resources/regress-52192-syntax-error.js: Added.
  • http/tests/security/resources/regress-52192-throw-error.js: Added.

(catch):

Location:
trunk
Files:
5 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r202456 r202460  
     12016-06-24  Mark Lam  <mark.lam@apple.com>
     2
     3        [JSC] Error prototypes are called on remote scripts.
     4        https://bugs.webkit.org/show_bug.cgi?id=52192
     5
     6        Reviewed by Keith Miller.
     7
     8        The added test will test the following combinations of factors:
     9
     10        1. Explicitly throwing an error of each of the types of JS errors i.e.
     11           Error, EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError.
     12        2. Validating that the error received in window.onerror does not leak any info.
     13        3. Validating that the 'name' and 'toString' getters set on the error prototype
     14           object does not get invoked for creating the error message to be passed to
     15           window.error.
     16
     17        * http/tests/security/regress-52192-expected.txt: Added.
     18        * http/tests/security/regress-52192.html: Added.
     19        * http/tests/security/resources/regress-52192-syntax-error.js: Added.
     20        * http/tests/security/resources/regress-52192-throw-error.js: Added.
     21        (catch):
     22
    1232016-06-24  Myles C. Maxfield  <mmaxfield@apple.com>
    224
  • trunk/Source/JavaScriptCore/ChangeLog

    r202458 r202460  
     12016-06-24  Mark Lam  <mark.lam@apple.com>
     2
     3        [JSC] Error prototypes are called on remote scripts.
     4        https://bugs.webkit.org/show_bug.cgi?id=52192
     5
     6        Reviewed by Keith Miller.
     7
     8        Added a sanitizedToString() to the Error instance object so that it can be used
     9        to get an error string without invoking getters and proxies.
     10
     11        * runtime/ErrorInstance.cpp:
     12        (JSC::ErrorInstance::finishCreation):
     13        (JSC::ErrorInstance::sanitizedToString):
     14        * runtime/ErrorInstance.h:
     15        (JSC::ErrorInstance::createStructure):
     16        (JSC::ErrorInstance::runtimeTypeForCause):
     17        (JSC::ErrorInstance::clearRuntimeTypeForCause):
     18
    1192016-06-24  Commit Queue  <commit-queue@webkit.org>
    220
  • trunk/Source/JavaScriptCore/runtime/ErrorInstance.cpp

    r201830 r202460  
    11/*
    22 *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
    3  *  Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
     3 *  Copyright (C) 2003, 2008, 2016 Apple Inc. All rights reserved.
    44 *
    55 *  This library is free software; you can redistribute it and/or
     
    152152    }
    153153}
    154    
     154
     155// Based on ErrorPrototype's errorProtoFuncToString(), but is modified to
     156// have no observable side effects to the user (i.e. does not call proxies,
     157// and getters).
     158String ErrorInstance::sanitizedToString(ExecState* exec)
     159{
     160    VM& vm = exec->vm();
     161
     162    JSValue nameValue;
     163    auto namePropertName = vm.propertyNames->name;
     164    PropertySlot nameSlot(this, PropertySlot::InternalMethodType::VMInquiry);
     165
     166    JSValue currentObj = this;
     167    unsigned prototypeDepth = 0;
     168
     169    // We only check the current object and its prototype (2 levels) because normal
     170    // Error objects may have a name property, and if not, its prototype should have
     171    // a name property for the type of error e.g. "SyntaxError".
     172    while (currentObj.isCell() && prototypeDepth++ < 2) {
     173        JSObject* obj = jsCast<JSObject*>(currentObj);
     174        if (JSObject::getOwnPropertySlot(obj, exec, namePropertName, nameSlot) && nameSlot.isValue()) {
     175            nameValue = nameSlot.getValue(exec, namePropertName);
     176            break;
     177        }
     178        currentObj = obj->getPrototypeDirect();
     179    }
     180    ASSERT(!vm.exception());
     181
     182    String nameString;
     183    if (!nameValue)
     184        nameString = ASCIILiteral("Error");
     185    else {
     186        nameString = nameValue.toString(exec)->value(exec);
     187        if (vm.exception())
     188            return String();
     189    }
     190
     191    JSValue messageValue;
     192    auto messagePropertName = vm.propertyNames->message;
     193    PropertySlot messageSlot(this, PropertySlot::InternalMethodType::VMInquiry);
     194    if (JSObject::getOwnPropertySlot(this, exec, messagePropertName, messageSlot) && messageSlot.isValue())
     195        messageValue = messageSlot.getValue(exec, messagePropertName);
     196    ASSERT(!vm.exception());
     197
     198    String messageString;
     199    if (!messageValue)
     200        messageString = String();
     201    else {
     202        messageString = messageValue.toString(exec)->value(exec);
     203        if (vm.exception())
     204            return String();
     205    }
     206
     207    if (!nameString.length())
     208        return messageString;
     209
     210    if (!messageString.length())
     211        return nameString;
     212
     213    StringBuilder builder;
     214    builder.append(nameString);
     215    builder.append(": ");
     216    builder.append(messageString);
     217    return builder.toString();
     218}
     219
    155220} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/ErrorInstance.h

    r182495 r202460  
    11/*
    22 *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
    3  *  Copyright (C) 2008 Apple Inc. All rights reserved.
     3 *  Copyright (C) 2008, 2016 Apple Inc. All rights reserved.
    44 *
    55 *  This library is free software; you can redistribute it and/or
     
    3636    typedef String (*SourceAppender) (const String& originalMessage, const String& sourceText, RuntimeType, SourceTextWhereErrorOccurred);
    3737
    38     DECLARE_INFO;
     38    DECLARE_EXPORT_INFO;
    3939
    4040    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
     
    6767    void clearRuntimeTypeForCause() { m_runtimeTypeForCause = TypeNothing; }
    6868
     69    JS_EXPORT_PRIVATE String sanitizedToString(ExecState*);
     70
    6971protected:
    7072    explicit ErrorInstance(VM&, Structure*);
  • trunk/Source/WebCore/ChangeLog

    r202459 r202460  
     12016-06-24  Mark Lam  <mark.lam@apple.com>
     2
     3        [JSC] Error prototypes are called on remote scripts.
     4        https://bugs.webkit.org/show_bug.cgi?id=52192
     5
     6        Reviewed by Keith Miller.
     7
     8        Test: http/tests/security/regress-52192.html
     9
     10        Parsing errors are reported to the main script's window.onerror function.  AFAIK,
     11        both Chrome and Firefox have the error reporting mechanism use an internal
     12        sanitized version of Error.prototype.toString() that will not invoke any getters
     13        or proxies instead.
     14
     15        This patch fixes this issue by matching Chrome and Firefox's behavior.
     16
     17        Note: we did not choose to make error objects and prototypes read-only because
     18        that was observed to have broken the web.
     19        See https://bugs.chromium.org/p/chromium/issues/detail?id=69187#c73
     20
     21        Credit for reporting this issue goes to Daniel Divricean (http://divricean.ro).
     22
     23        * bindings/js/JSDOMBinding.cpp:
     24        (WebCore::reportException):
     25        * ForwardingHeaders/runtime/ErrorInstance.h: Added.
     26
    1272016-06-24  Jer Noble  <jer.noble@apple.com>
    228
  • trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp

    r202023 r202460  
    11/*
    22 *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
    3  *  Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013 Apple Inc. All rights reserved.
     3 *  Copyright (C) 2004-2011, 2013, 2016 Apple Inc. All rights reserved.
    44 *  Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
    55 *  Copyright (C) 2013 Michael Pruett <michael@68k.org>
     
    4444#include <runtime/Error.h>
    4545#include <runtime/ErrorHandlingScope.h>
     46#include <runtime/ErrorInstance.h>
    4647#include <runtime/Exception.h>
    4748#include <runtime/ExceptionHelpers.h>
     
    198199
    199200    String errorMessage;
    200     if (ExceptionBase* exceptionBase = toExceptionBase(exception->value()))
     201    JSValue exceptionValue = exception->value();
     202    if (ExceptionBase* exceptionBase = toExceptionBase(exceptionValue))
    201203        errorMessage = exceptionBase->message() + ": "  + exceptionBase->description();
    202204    else {
    203205        // FIXME: <http://webkit.org/b/115087> Web Inspector: WebCore::reportException should not evaluate JavaScript handling exceptions
    204206        // If this is a custom exception object, call toString on it to try and get a nice string representation for the exception.
    205         errorMessage = exception->value().toString(exec)->value(exec);
     207        if (ErrorInstance* error = jsDynamicCast<ErrorInstance*>(exceptionValue))
     208            errorMessage = error->sanitizedToString(exec);
     209        else
     210            errorMessage = exceptionValue.toString(exec)->value(exec);
    206211
    207212        // We need to clear any new exception that may be thrown in the toString() call above.
Note: See TracChangeset for help on using the changeset viewer.