1 : #include "tests.h"
2 :
3 : JSPrincipals system_principals = {
4 : 1
5 : };
6 :
7 : JSClass global_class = {
8 : "global",
9 : JSCLASS_IS_GLOBAL | JSCLASS_GLOBAL_FLAGS,
10 : JS_PropertyStub,
11 : JS_PropertyStub,
12 : JS_PropertyStub,
13 : JS_StrictPropertyStub,
14 : JS_EnumerateStub,
15 : JS_ResolveStub,
16 : JS_ConvertStub
17 : };
18 :
19 1 : JS::Anchor<JSObject *> trusted_glob, trusted_fun;
20 :
21 : JSBool
22 1 : CallTrusted(JSContext *cx, unsigned argc, jsval *vp)
23 : {
24 1 : if (!JS_SaveFrameChain(cx))
25 0 : return JS_FALSE;
26 :
27 1 : JSBool ok = JS_FALSE;
28 : {
29 2 : JSAutoEnterCompartment ac;
30 1 : ok = ac.enter(cx, trusted_glob.get());
31 1 : if (!ok)
32 : goto out;
33 1 : ok = JS_CallFunctionValue(cx, NULL, OBJECT_TO_JSVAL(trusted_fun.get()),
34 1 : 0, NULL, vp);
35 : }
36 : out:
37 1 : JS_RestoreFrameChain(cx);
38 1 : return ok;
39 : }
40 :
41 4 : BEGIN_TEST(testChromeBuffer)
42 : {
43 1 : JS_SetTrustedPrincipals(rt, &system_principals);
44 :
45 : JSFunction *fun;
46 : JSObject *o;
47 :
48 1 : CHECK(o = JS_NewCompartmentAndGlobalObject(cx, &global_class, &system_principals));
49 1 : trusted_glob.set(o);
50 :
51 : /*
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.
55 : */
56 : {
57 : {
58 2 : JSAutoEnterCompartment ac;
59 1 : CHECK(ac.enter(cx, trusted_glob.get()));
60 1 : const char *paramName = "x";
61 1 : const char *bytes = "return x ? 1 + trusted(x-1) : 0";
62 1 : CHECK(fun = JS_CompileFunctionForPrincipals(cx, trusted_glob.get(), &system_principals,
63 : "trusted", 1, ¶mName, bytes, strlen(bytes),
64 : "", 0));
65 2 : trusted_fun.set(JS_GetFunctionObject(fun));
66 : }
67 :
68 1 : jsval v = OBJECT_TO_JSVAL(trusted_fun.get());
69 1 : CHECK(JS_WrapValue(cx, &v));
70 :
71 1 : const char *paramName = "trusted";
72 : const char *bytes = "try { "
73 : " return untrusted(trusted); "
74 : "} catch (e) { "
75 : " return trusted(100); "
76 1 : "} ";
77 1 : CHECK(fun = JS_CompileFunction(cx, global, "untrusted", 1, ¶mName,
78 : bytes, strlen(bytes), "", 0));
79 :
80 : jsval rval;
81 1 : CHECK(JS_CallFunction(cx, NULL, fun, 1, &v, &rval));
82 1 : CHECK(JSVAL_TO_INT(rval) == 100);
83 : }
84 :
85 : /*
86 : * Check that content called from chrome in the reserved-buffer space
87 : * immediately ooms.
88 : */
89 : {
90 : {
91 2 : JSAutoEnterCompartment ac;
92 1 : CHECK(ac.enter(cx, trusted_glob.get()));
93 1 : const char *paramName = "untrusted";
94 : const char *bytes = "try { "
95 : " untrusted(); "
96 : "} catch (e) { "
97 : " return 'From trusted: ' + e; "
98 1 : "} ";
99 1 : CHECK(fun = JS_CompileFunctionForPrincipals(cx, trusted_glob.get(), &system_principals,
100 : "trusted", 1, ¶mName, bytes, strlen(bytes),
101 : "", 0));
102 2 : trusted_fun.set(JS_GetFunctionObject(fun));
103 : }
104 :
105 1 : jsval v = OBJECT_TO_JSVAL(trusted_fun.get());
106 1 : CHECK(JS_WrapValue(cx, &v));
107 :
108 1 : const char *paramName = "trusted";
109 : const char *bytes = "try { "
110 : " return untrusted(trusted); "
111 : "} catch (e) { "
112 : " return trusted(untrusted); "
113 1 : "} ";
114 1 : CHECK(fun = JS_CompileFunction(cx, global, "untrusted", 1, ¶mName,
115 : bytes, strlen(bytes), "", 0));
116 :
117 : jsval rval;
118 1 : CHECK(JS_CallFunction(cx, NULL, fun, 1, &v, &rval));
119 : JSBool match;
120 1 : CHECK(JS_StringEqualsAscii(cx, JSVAL_TO_STRING(rval), "From trusted: InternalError: too much recursion", &match));
121 1 : CHECK(match);
122 : }
123 :
124 : /*
125 : * Check that JS_SaveFrameChain called on the way from content to chrome
126 : * (say, as done by XPCJSContextSTack::Push) works.
127 : */
128 : {
129 : {
130 2 : JSAutoEnterCompartment ac;
131 1 : CHECK(ac.enter(cx, trusted_glob.get()));
132 1 : const char *bytes = "return 42";
133 1 : CHECK(fun = JS_CompileFunctionForPrincipals(cx, trusted_glob.get(), &system_principals,
134 : "trusted", 0, NULL, bytes, strlen(bytes),
135 : "", 0));
136 2 : trusted_fun.set(JS_GetFunctionObject(fun));
137 : }
138 :
139 1 : JSFunction *fun = JS_NewFunction(cx, CallTrusted, 0, 0, global, "callTrusted");
140 2 : JS::Anchor<JSObject *> callTrusted(JS_GetFunctionObject(fun));
141 :
142 1 : const char *paramName = "f";
143 : const char *bytes = "try { "
144 : " return untrusted(trusted); "
145 : "} catch (e) { "
146 : " return f(); "
147 1 : "} ";
148 1 : CHECK(fun = JS_CompileFunction(cx, global, "untrusted", 1, ¶mName,
149 : bytes, strlen(bytes), "", 0));
150 :
151 1 : jsval arg = OBJECT_TO_JSVAL(callTrusted.get());
152 : jsval rval;
153 1 : CHECK(JS_CallFunction(cx, NULL, fun, 1, &arg, &rval));
154 1 : CHECK(JSVAL_TO_INT(rval) == 42);
155 : }
156 :
157 1 : return true;
158 : }
159 3 : END_TEST(testChromeBuffer)
|