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