1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/Utf8.h" // mozilla::Utf8Unit
9 #include "js/CallAndConstruct.h" // JS_CallFunctionValue
10 #include "js/CompilationAndEvaluation.h" // JS::CompileFunction
11 #include "js/ContextOptions.h"
12 #include "js/GlobalObject.h" // JS_NewGlobalObject
13 #include "js/PropertyAndElement.h" // JS_DefineProperty
14 #include "js/SourceText.h" // JS::Source{Ownership,Text}
15 #include "jsapi-tests/tests.h"
16 #include "util/Text.h"
18 static TestJSPrincipals
system_principals(1);
20 static const JSClass global_class
= {"global",
21 JSCLASS_IS_GLOBAL
| JSCLASS_GLOBAL_FLAGS
,
22 &JS::DefaultGlobalClassOps
};
24 static JS::PersistentRootedObject trusted_glob
;
25 static JS::PersistentRootedObject trusted_fun
;
27 static bool CallTrusted(JSContext
* cx
, unsigned argc
, JS::Value
* vp
) {
28 JS::CallArgs args
= JS::CallArgsFromVp(argc
, vp
);
32 JSAutoRealm
ar(cx
, trusted_glob
);
33 JS::RootedValue
funVal(cx
, JS::ObjectValue(*trusted_fun
));
34 ok
= JS_CallFunctionValue(cx
, nullptr, funVal
,
35 JS::HandleValueArray::empty(), args
.rval());
40 BEGIN_TEST(testChromeBuffer
) {
41 JS_SetTrustedPrincipals(cx
, &system_principals
);
43 JS::RealmOptions options
;
45 JS_NewGlobalObject(cx
, &global_class
, &system_principals
,
46 JS::FireOnNewGlobalHook
, options
));
49 JS::RootedFunction
fun(cx
);
52 * Check that, even after untrusted content has exhausted the stack, code
53 * compiled with "trusted principals" can run using reserved trusted-only
57 // Disable the JIT because if we don't this test fails. See bug 1160414.
58 uint32_t oldBaselineInterpreterEnabled
;
59 CHECK(JS_GetGlobalJitCompilerOption(
60 cx
, JSJITCOMPILER_BASELINE_INTERPRETER_ENABLE
,
61 &oldBaselineInterpreterEnabled
));
62 JS_SetGlobalJitCompilerOption(cx
, JSJITCOMPILER_BASELINE_INTERPRETER_ENABLE
,
64 uint32_t oldBaselineJitEnabled
;
65 CHECK(JS_GetGlobalJitCompilerOption(cx
, JSJITCOMPILER_BASELINE_ENABLE
,
66 &oldBaselineJitEnabled
));
67 JS_SetGlobalJitCompilerOption(cx
, JSJITCOMPILER_BASELINE_ENABLE
, 0);
69 JSAutoRealm
ar(cx
, trusted_glob
);
70 const char* paramName
= "x";
71 static const char bytes
[] = "return x ? 1 + trusted(x-1) : 0";
73 JS::SourceText
<mozilla::Utf8Unit
> srcBuf
;
74 CHECK(srcBuf
.init(cx
, bytes
, js_strlen(bytes
),
75 JS::SourceOwnership::Borrowed
));
77 JS::CompileOptions
options(cx
);
78 options
.setFileAndLine("", 0);
80 JS::RootedObjectVector
emptyScopeChain(cx
);
81 fun
= JS::CompileFunction(cx
, emptyScopeChain
, options
, "trusted", 1,
84 CHECK(JS_DefineProperty(cx
, trusted_glob
, "trusted", fun
,
86 trusted_fun
.init(cx
, JS_GetFunctionObject(fun
));
89 JS::RootedValue
v(cx
, JS::ObjectValue(*trusted_fun
));
90 CHECK(JS_WrapValue(cx
, &v
));
92 const char* paramName
= "trusted";
93 static const char bytes
[] =
95 " return untrusted(trusted); "
98 " return trusted(100); "
104 JS::SourceText
<mozilla::Utf8Unit
> srcBuf
;
105 CHECK(srcBuf
.init(cx
, bytes
, js_strlen(bytes
),
106 JS::SourceOwnership::Borrowed
));
108 JS::CompileOptions
options(cx
);
109 options
.setFileAndLine("", 0);
111 JS::RootedObjectVector
emptyScopeChain(cx
);
112 fun
= JS::CompileFunction(cx
, emptyScopeChain
, options
, "untrusted", 1,
115 CHECK(JS_DefineProperty(cx
, global
, "untrusted", fun
, JSPROP_ENUMERATE
));
117 JS::RootedValue
rval(cx
);
118 CHECK(JS_CallFunction(cx
, nullptr, fun
, JS::HandleValueArray(v
), &rval
));
119 CHECK(rval
.toInt32() == 100);
120 JS_SetGlobalJitCompilerOption(cx
, JSJITCOMPILER_BASELINE_INTERPRETER_ENABLE
,
121 oldBaselineInterpreterEnabled
);
122 JS_SetGlobalJitCompilerOption(cx
, JSJITCOMPILER_BASELINE_ENABLE
,
123 oldBaselineJitEnabled
);
127 * Check that content called from chrome in the reserved-buffer space
132 JSAutoRealm
ar(cx
, trusted_glob
);
134 const char* paramName
= "untrusted";
135 static const char bytes
[] =
140 " * Careful! We must not reenter JS "
141 " * that might try to push a frame. "
143 " return 'From trusted: ' + "
144 " e.name + ': ' + e.message; "
147 JS::SourceText
<mozilla::Utf8Unit
> srcBuf
;
148 CHECK(srcBuf
.init(cx
, bytes
, js_strlen(bytes
),
149 JS::SourceOwnership::Borrowed
));
151 JS::CompileOptions
options(cx
);
152 options
.setFileAndLine("", 0);
154 JS::RootedObjectVector
emptyScopeChain(cx
);
155 fun
= JS::CompileFunction(cx
, emptyScopeChain
, options
, "trusted", 1,
158 CHECK(JS_DefineProperty(cx
, trusted_glob
, "trusted", fun
,
160 trusted_fun
= JS_GetFunctionObject(fun
);
163 JS::RootedValue
v(cx
, JS::ObjectValue(*trusted_fun
));
164 CHECK(JS_WrapValue(cx
, &v
));
166 const char* paramName
= "trusted";
167 static const char bytes
[] =
169 " return untrusted(trusted); "
171 " return trusted(untrusted); "
174 JS::SourceText
<mozilla::Utf8Unit
> srcBuf
;
175 CHECK(srcBuf
.init(cx
, bytes
, js_strlen(bytes
),
176 JS::SourceOwnership::Borrowed
));
178 JS::CompileOptions
options(cx
);
179 options
.setFileAndLine("", 0);
181 JS::RootedObjectVector
emptyScopeChain(cx
);
182 fun
= JS::CompileFunction(cx
, emptyScopeChain
, options
, "untrusted", 1,
185 CHECK(JS_DefineProperty(cx
, global
, "untrusted", fun
, JSPROP_ENUMERATE
));
187 JS::RootedValue
rval(cx
);
188 CHECK(JS_CallFunction(cx
, nullptr, fun
, JS::HandleValueArray(v
), &rval
));
189 #ifndef JS_SIMULATOR_ARM64
190 // The ARM64 simulator does not share a common implementation with the other
191 // simulators, and has slightly different end-of-stack behavior. Instead of
192 // failing with "too much recursion," it executes one more function call and
193 // fails with a type error. This behavior is not incorrect.
195 CHECK(JS_StringEqualsAscii(
196 cx
, rval
.toString(), "From trusted: InternalError: too much recursion",
204 JSAutoRealm
ar(cx
, trusted_glob
);
206 static const char bytes
[] = "return 42";
208 JS::SourceText
<mozilla::Utf8Unit
> srcBuf
;
209 CHECK(srcBuf
.init(cx
, bytes
, js_strlen(bytes
),
210 JS::SourceOwnership::Borrowed
));
212 JS::CompileOptions
options(cx
);
213 options
.setFileAndLine("", 0);
215 JS::RootedObjectVector
emptyScopeChain(cx
);
216 fun
= JS::CompileFunction(cx
, emptyScopeChain
, options
, "trusted", 0,
219 CHECK(JS_DefineProperty(cx
, trusted_glob
, "trusted", fun
,
221 trusted_fun
= JS_GetFunctionObject(fun
);
224 JS::RootedFunction
fun(
225 cx
, JS_NewFunction(cx
, CallTrusted
, 0, 0, "callTrusted"));
226 JS::RootedObject
callTrusted(cx
, JS_GetFunctionObject(fun
));
228 const char* paramName
= "f";
229 static const char bytes
[] =
231 " return untrusted(trusted); "
236 JS::SourceText
<mozilla::Utf8Unit
> srcBuf
;
237 CHECK(srcBuf
.init(cx
, bytes
, js_strlen(bytes
),
238 JS::SourceOwnership::Borrowed
));
240 JS::CompileOptions
options(cx
);
241 options
.setFileAndLine("", 0);
243 JS::RootedObjectVector
emptyScopeChain(cx
);
244 fun
= JS::CompileFunction(cx
, emptyScopeChain
, options
, "untrusted", 1,
247 CHECK(JS_DefineProperty(cx
, global
, "untrusted", fun
, JSPROP_ENUMERATE
));
249 JS::RootedValue
arg(cx
, JS::ObjectValue(*callTrusted
));
250 JS::RootedValue
rval(cx
);
251 CHECK(JS_CallFunction(cx
, nullptr, fun
, JS::HandleValueArray(arg
), &rval
));
252 CHECK(rval
.toInt32() == 42);
257 END_TEST(testChromeBuffer
)