Bug 1832850 - Part 5: Move the allocateObject definition into gc/Nursery.h r=jandem
[gecko.git] / js / src / jsapi-tests / testChromeBuffer.cpp
blob251d6a18ad17ce0082e9a90d7f6017343a3b7031
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);
30 bool ok = false;
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());
37 return ok;
40 BEGIN_TEST(testChromeBuffer) {
41 JS_SetTrustedPrincipals(cx, &system_principals);
43 JS::RealmOptions options;
44 trusted_glob.init(cx,
45 JS_NewGlobalObject(cx, &global_class, &system_principals,
46 JS::FireOnNewGlobalHook, options));
47 CHECK(trusted_glob);
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
54 * buffer space.
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,
63 0);
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,
82 &paramName, srcBuf);
83 CHECK(fun);
84 CHECK(JS_DefineProperty(cx, trusted_glob, "trusted", fun,
85 JSPROP_ENUMERATE));
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[] =
94 "try { "
95 " return untrusted(trusted); "
96 "} catch (e) { "
97 " try { "
98 " return trusted(100); "
99 " } catch(e) { "
100 " return -1; "
101 " } "
102 "} ";
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,
113 &paramName, srcBuf);
114 CHECK(fun);
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
128 * immediately ooms.
132 JSAutoRealm ar(cx, trusted_glob);
134 const char* paramName = "untrusted";
135 static const char bytes[] =
136 "try { "
137 " untrusted(); "
138 "} catch (e) { "
139 " /* "
140 " * Careful! We must not reenter JS "
141 " * that might try to push a frame. "
142 " */ "
143 " return 'From trusted: ' + "
144 " e.name + ': ' + e.message; "
145 "} ";
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,
156 &paramName, srcBuf);
157 CHECK(fun);
158 CHECK(JS_DefineProperty(cx, trusted_glob, "trusted", fun,
159 JSPROP_ENUMERATE));
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[] =
168 "try { "
169 " return untrusted(trusted); "
170 "} catch (e) { "
171 " return trusted(untrusted); "
172 "} ";
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,
183 &paramName, srcBuf);
184 CHECK(fun);
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.
194 bool match;
195 CHECK(JS_StringEqualsAscii(
196 cx, rval.toString(), "From trusted: InternalError: too much recursion",
197 &match));
198 CHECK(match);
199 #endif
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,
217 nullptr, srcBuf);
218 CHECK(fun);
219 CHECK(JS_DefineProperty(cx, trusted_glob, "trusted", fun,
220 JSPROP_ENUMERATE));
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[] =
230 "try { "
231 " return untrusted(trusted); "
232 "} catch (e) { "
233 " return f(); "
234 "} ";
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,
245 &paramName, srcBuf);
246 CHECK(fun);
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);
255 return true;
257 END_TEST(testChromeBuffer)