A stack overflow in the parsing of a builtin (called by createExecutable) cause a...
[WebKit-https.git] / Source / JavaScriptCore / runtime / FunctionPrototype.cpp
1 /*
2  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2003-2009, 2015-2016 Apple Inc. All rights reserved.
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Lesser General Public
7  *  License as published by the Free Software Foundation; either
8  *  version 2 of the License, or (at your option) any later version.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  Lesser General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Lesser General Public
16  *  License along with this library; if not, write to the Free Software
17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18  *
19  */
20
21 #include "config.h"
22 #include "FunctionPrototype.h"
23
24 #include "BuiltinExecutables.h"
25 #include "BuiltinNames.h"
26 #include "Error.h"
27 #include "GetterSetter.h"
28 #include "JSAsyncFunction.h"
29 #include "JSCInlines.h"
30 #include "JSFunction.h"
31 #include "JSStringInlines.h"
32 #include "Lexer.h"
33
34 namespace JSC {
35
36 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(FunctionPrototype);
37
38 const ClassInfo FunctionPrototype::s_info = { "Function", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(FunctionPrototype) };
39
40 static EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState*);
41
42 // ECMA 15.3.4
43 static EncodedJSValue JSC_HOST_CALL callFunctionPrototype(ExecState*)
44 {
45     return JSValue::encode(jsUndefined());
46 }
47
48 FunctionPrototype::FunctionPrototype(VM& vm, Structure* structure)
49     : InternalFunction(vm, structure, callFunctionPrototype, nullptr)
50 {
51 }
52
53 void FunctionPrototype::finishCreation(VM& vm, const String& name)
54 {
55     Base::finishCreation(vm, name);
56     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(0), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum);
57 }
58
59 void FunctionPrototype::addFunctionProperties(ExecState* exec, JSGlobalObject* globalObject, JSFunction** callFunction, JSFunction** applyFunction, JSFunction** hasInstanceSymbolFunction)
60 {
61     VM& vm = exec->vm();
62
63     JSFunction* toStringFunction = JSFunction::create(vm, globalObject, 0, vm.propertyNames->toString.string(), functionProtoFuncToString);
64     putDirectWithoutTransition(vm, vm.propertyNames->toString, toStringFunction, static_cast<unsigned>(PropertyAttribute::DontEnum));
65
66     *applyFunction = putDirectBuiltinFunctionWithoutTransition(vm, globalObject, vm.propertyNames->builtinNames().applyPublicName(), functionPrototypeApplyCodeGenerator(vm).value(), static_cast<unsigned>(PropertyAttribute::DontEnum));
67     *callFunction = putDirectBuiltinFunctionWithoutTransition(vm, globalObject, vm.propertyNames->builtinNames().callPublicName(), functionPrototypeCallCodeGenerator(vm).value(), static_cast<unsigned>(PropertyAttribute::DontEnum));
68     putDirectBuiltinFunctionWithoutTransition(vm, globalObject, vm.propertyNames->bind, functionPrototypeBindCodeGenerator(vm).value(), static_cast<unsigned>(PropertyAttribute::DontEnum));
69
70     *hasInstanceSymbolFunction = JSFunction::create(vm, functionPrototypeSymbolHasInstanceCodeGenerator(vm).value(), globalObject);
71     putDirectWithoutTransition(vm, vm.propertyNames->hasInstanceSymbol, *hasInstanceSymbolFunction, PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum);
72 }
73     
74 void FunctionPrototype::initRestrictedProperties(ExecState* exec, JSGlobalObject* globalObject)
75 {
76     VM& vm = exec->vm();
77     GetterSetter* errorGetterSetter = globalObject->throwTypeErrorArgumentsCalleeAndCallerGetterSetter();
78     putDirectAccessor(exec, vm.propertyNames->caller, errorGetterSetter, PropertyAttribute::DontEnum | PropertyAttribute::Accessor);
79     putDirectAccessor(exec, vm.propertyNames->arguments, errorGetterSetter, PropertyAttribute::DontEnum | PropertyAttribute::Accessor);
80 }
81
82 EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec)
83 {
84     VM& vm = exec->vm();
85     auto scope = DECLARE_THROW_SCOPE(vm);
86
87     JSValue thisValue = exec->thisValue();
88     if (thisValue.inherits<JSFunction>(vm)) {
89         JSFunction* function = jsCast<JSFunction*>(thisValue);
90         if (function->isHostOrBuiltinFunction()) {
91             scope.release();
92             return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(vm), "() {\n    [native code]\n}"));
93         }
94
95         FunctionExecutable* executable = function->jsExecutable();
96         if (executable->isClass()) {
97             StringView classSource = executable->classSource().view();
98             return JSValue::encode(jsString(exec, classSource.toStringWithoutCopying()));
99         }
100
101         if (thisValue.inherits<JSAsyncFunction>(vm)) {
102             String functionHeader = executable->isArrowFunction() ? "async " : "async function ";
103
104             StringView source = executable->source().provider()->getRange(
105                 executable->parametersStartOffset(),
106                 executable->parametersStartOffset() + executable->source().length());
107             return JSValue::encode(jsMakeNontrivialString(exec, functionHeader, function->name(vm), source));
108         }
109
110         String functionHeader = executable->isArrowFunction() ? "" : "function ";
111         
112         StringView source = executable->source().provider()->getRange(
113             executable->parametersStartOffset(),
114             executable->parametersStartOffset() + executable->source().length());
115         scope.release();
116         return JSValue::encode(jsMakeNontrivialString(exec, functionHeader, function->name(vm), source));
117     }
118
119     if (thisValue.inherits<InternalFunction>(vm)) {
120         InternalFunction* function = asInternalFunction(thisValue);
121         scope.release();
122         return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(), "() {\n    [native code]\n}"));
123     }
124
125     if (thisValue.isObject()) {
126         JSObject* object = asObject(thisValue);
127         if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
128             CallData callData;
129             if (object->methodTable(vm)->getCallData(object, callData) != CallType::None) {
130                 if (auto* classInfo = object->classInfo(vm)) {
131                     scope.release();
132                     return JSValue::encode(jsMakeNontrivialString(exec, "function ", classInfo->className, "() {\n    [native code]\n}"));
133                 }
134             }
135         }
136     }
137
138     return throwVMTypeError(exec, scope);
139 }
140
141 } // namespace JSC