1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sw=4 et tw=99:
3 : */
4 :
5 : #include "tests.h"
6 : #include "jsscript.h"
7 : #include "jsxdrapi.h"
8 :
9 : static JSScript *
10 18 : CompileScriptForPrincipalsVersionOrigin(JSContext *cx, JSObject *obj,
11 : JSPrincipals *principals, JSPrincipals *originPrincipals,
12 : const char *bytes, size_t nbytes,
13 : const char *filename, unsigned lineno,
14 : JSVersion version)
15 : {
16 : size_t nchars;
17 18 : if (!JS_DecodeBytes(cx, bytes, nbytes, NULL, &nchars))
18 0 : return NULL;
19 18 : jschar *chars = static_cast<jschar *>(JS_malloc(cx, nchars * sizeof(jschar)));
20 18 : if (!chars)
21 0 : return NULL;
22 18 : JS_ALWAYS_TRUE(JS_DecodeBytes(cx, bytes, nbytes, chars, &nchars));
23 : JSScript *script = JS_CompileUCScriptForPrincipalsVersionOrigin(cx, obj,
24 : principals, originPrincipals,
25 : chars, nchars,
26 18 : filename, lineno, version);
27 18 : free(chars);
28 18 : return script;
29 : }
30 :
31 : template<typename T>
32 : T *
33 21 : FreezeThawImpl(JSContext *cx, T *thing, JSBool (*xdrAction)(JSXDRState *xdr, T **))
34 : {
35 : // freeze
36 21 : JSXDRState *w = JS_XDRNewMem(cx, JSXDR_ENCODE);
37 21 : if (!w)
38 0 : return NULL;
39 :
40 21 : void *memory = NULL;
41 : uint32_t nbytes;
42 21 : if (xdrAction(w, &thing)) {
43 21 : void *p = JS_XDRMemGetData(w, &nbytes);
44 21 : if (p) {
45 21 : memory = JS_malloc(cx, nbytes);
46 21 : if (memory)
47 21 : memcpy(memory, p, nbytes);
48 : }
49 : }
50 21 : JS_XDRDestroy(w);
51 21 : if (!memory)
52 0 : return NULL;
53 :
54 : // thaw
55 21 : JSXDRState *r = JS_XDRNewMem(cx, JSXDR_DECODE);
56 21 : JS_XDRMemSetData(r, memory, nbytes);
57 21 : if (!xdrAction(r, &thing))
58 0 : thing = NULL;
59 21 : JS_XDRDestroy(r); // this frees `memory
60 21 : return thing;
61 : }
62 :
63 : static JSScript *
64 15 : FreezeThaw(JSContext *cx, JSScript *script)
65 : {
66 15 : return FreezeThawImpl(cx, script, JS_XDRScript);
67 : }
68 :
69 : static JSObject *
70 6 : FreezeThaw(JSContext *cx, JSObject *funobj)
71 : {
72 6 : return FreezeThawImpl(cx, funobj, JS_XDRFunctionObject);
73 : }
74 :
75 : static JSPrincipals testPrincipals[] = {
76 : { 1 },
77 : { 1 },
78 : };
79 :
80 : static JSBool
81 30 : TranscodePrincipals(JSXDRState *xdr, JSPrincipals **principalsp)
82 : {
83 : uint32_t index;
84 30 : if (xdr->mode == JSXDR_ENCODE) {
85 15 : JSPrincipals *p = *principalsp;
86 21 : for (index = 0; ; ++index) {
87 21 : if (index == mozilla::ArrayLength(testPrincipals))
88 0 : return false;
89 21 : if (p == &testPrincipals[index])
90 : break;
91 : }
92 : }
93 :
94 30 : if (!JS_XDRUint32(xdr, &index))
95 0 : return false;
96 :
97 30 : if (xdr->mode == JSXDR_DECODE) {
98 15 : if (index >= mozilla::ArrayLength(testPrincipals))
99 0 : return false;
100 15 : *principalsp = &testPrincipals[index];
101 15 : JS_HoldPrincipals(*principalsp);
102 : }
103 :
104 30 : return true;
105 : }
106 :
107 4 : BEGIN_TEST(testXDR_principals)
108 : {
109 : static const JSSecurityCallbacks seccb = {
110 : NULL,
111 : NULL,
112 : TranscodePrincipals,
113 : NULL,
114 : NULL
115 : };
116 :
117 1 : JS_SetSecurityCallbacks(rt, &seccb);
118 :
119 : JSScript *script;
120 4 : for (int i = TEST_FIRST; i != TEST_END; ++i) {
121 3 : script = createScriptViaXDR(NULL, NULL, i);
122 3 : CHECK(script);
123 3 : CHECK(!JS_GetScriptPrincipals(cx, script));
124 3 : CHECK(!JS_GetScriptOriginPrincipals(cx, script));
125 :
126 3 : script = createScriptViaXDR(NULL, NULL, i);
127 3 : CHECK(script);
128 3 : CHECK(!JS_GetScriptPrincipals(cx, script));
129 3 : CHECK(!JS_GetScriptOriginPrincipals(cx, script));
130 :
131 3 : script = createScriptViaXDR(&testPrincipals[0], NULL, i);
132 3 : CHECK(script);
133 3 : CHECK(JS_GetScriptPrincipals(cx, script) == &testPrincipals[0]);
134 3 : CHECK(JS_GetScriptOriginPrincipals(cx, script) == &testPrincipals[0]);
135 :
136 3 : script = createScriptViaXDR(&testPrincipals[0], &testPrincipals[0], i);
137 3 : CHECK(script);
138 3 : CHECK(JS_GetScriptPrincipals(cx, script) == &testPrincipals[0]);
139 3 : CHECK(JS_GetScriptOriginPrincipals(cx, script) == &testPrincipals[0]);
140 :
141 3 : script = createScriptViaXDR(&testPrincipals[0], &testPrincipals[1], i);
142 3 : CHECK(script);
143 3 : CHECK(JS_GetScriptPrincipals(cx, script) == &testPrincipals[0]);
144 3 : CHECK(JS_GetScriptOriginPrincipals(cx, script) == &testPrincipals[1]);
145 :
146 3 : script = createScriptViaXDR(NULL, &testPrincipals[1], i);
147 3 : CHECK(script);
148 3 : CHECK(!JS_GetScriptPrincipals(cx, script));
149 3 : CHECK(JS_GetScriptOriginPrincipals(cx, script) == &testPrincipals[1]);
150 : }
151 :
152 1 : return true;
153 : }
154 :
155 : enum TestCase {
156 : TEST_FIRST,
157 : TEST_SCRIPT = TEST_FIRST,
158 : TEST_FUNCTION,
159 : TEST_SERIALIZED_FUNCTION,
160 : TEST_END
161 : };
162 :
163 18 : JSScript *createScriptViaXDR(JSPrincipals *prin, JSPrincipals *orig, int testCase)
164 : {
165 : const char src[] =
166 : "function f() { return 1; }\n"
167 18 : "f;\n";
168 :
169 : JSScript *script = CompileScriptForPrincipalsVersionOrigin(cx, global, prin, orig,
170 : src, strlen(src), "test", 1,
171 18 : JSVERSION_DEFAULT);
172 18 : if (!script)
173 0 : return NULL;
174 :
175 18 : if (testCase == TEST_SCRIPT || testCase == TEST_SERIALIZED_FUNCTION) {
176 12 : script = FreezeThaw(cx, script);
177 12 : if (!script)
178 0 : return NULL;
179 12 : if (testCase == TEST_SCRIPT)
180 6 : return script;
181 : }
182 :
183 : JS::Value v;
184 12 : JSBool ok = JS_ExecuteScript(cx, global, script, &v);
185 12 : if (!ok || !v.isObject())
186 0 : return NULL;
187 12 : JSObject *funobj = &v.toObject();
188 12 : if (testCase == TEST_FUNCTION) {
189 6 : funobj = FreezeThaw(cx, funobj);
190 6 : if (!funobj)
191 0 : return NULL;
192 : }
193 12 : return JS_GetFunctionScript(cx, JS_GetObjectFunction(funobj));
194 : }
195 :
196 1 : END_TEST(testXDR_principals)
197 :
198 4 : BEGIN_TEST(testXDR_atline)
199 : {
200 1 : JS_ToggleOptions(cx, JSOPTION_ATLINE);
201 1 : CHECK(JS_GetOptions(cx) & JSOPTION_ATLINE);
202 :
203 : const char src[] =
204 : "//@line 100 \"foo\"\n"
205 : "function nested() { }\n"
206 : "//@line 200 \"bar\"\n"
207 1 : "nested;\n";
208 :
209 1 : JSScript *script = JS_CompileScript(cx, global, src, strlen(src), "internal", 1);
210 1 : CHECK(script);
211 1 : CHECK(script = FreezeThaw(cx, script));
212 1 : CHECK(!strcmp("bar", JS_GetScriptFilename(cx, script)));
213 :
214 : JS::Value v;
215 1 : JSBool ok = JS_ExecuteScript(cx, global, script, &v);
216 1 : CHECK(ok);
217 1 : CHECK(v.isObject());
218 :
219 1 : JSObject *funobj = &v.toObject();
220 1 : script = JS_GetFunctionScript(cx, JS_GetObjectFunction(funobj));
221 1 : CHECK(!strcmp("foo", JS_GetScriptFilename(cx, script)));
222 :
223 1 : return true;
224 : }
225 :
226 1 : END_TEST(testXDR_atline)
227 :
228 4 : BEGIN_TEST(testXDR_bug506491)
229 : {
230 : const char *s =
231 : "function makeClosure(s, name, value) {\n"
232 : " eval(s);\n"
233 : " return let (n = name, v = value) function () { return String(v); };\n"
234 : "}\n"
235 1 : "var f = makeClosure('0;', 'status', 'ok');\n";
236 :
237 : // compile
238 1 : JSScript *script = JS_CompileScript(cx, global, s, strlen(s), __FILE__, __LINE__);
239 1 : CHECK(script);
240 :
241 1 : script = FreezeThaw(cx, script);
242 1 : CHECK(script);
243 :
244 : // execute
245 2 : jsvalRoot v2(cx);
246 1 : CHECK(JS_ExecuteScript(cx, global, script, v2.addr()));
247 :
248 : // try to break the Block object that is the parent of f
249 1 : JS_GC(cx);
250 :
251 : // confirm
252 1 : EVAL("f() === 'ok';\n", v2.addr());
253 2 : jsvalRoot trueval(cx, JSVAL_TRUE);
254 1 : CHECK_SAME(v2, trueval);
255 1 : return true;
256 : }
257 1 : END_TEST(testXDR_bug506491)
258 :
259 4 : BEGIN_TEST(testXDR_bug516827)
260 : {
261 : // compile an empty script
262 1 : JSScript *script = JS_CompileScript(cx, global, "", 0, __FILE__, __LINE__);
263 1 : CHECK(script);
264 :
265 1 : script = FreezeThaw(cx, script);
266 1 : CHECK(script);
267 :
268 : // execute with null result meaning no result wanted
269 1 : CHECK(JS_ExecuteScript(cx, global, script, NULL));
270 1 : return true;
271 : }
272 3 : END_TEST(testXDR_bug516827)
|