1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : *
3 : * ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is Mozilla Communicator client code, released
17 : * March 31, 1998.
18 : *
19 : * The Initial Developer of the Original Code is
20 : * Netscape Communications Corporation.
21 : * Portions created by the Initial Developer are Copyright (C) 1998
22 : * the Initial Developer. All Rights Reserved.
23 : *
24 : * Contributor(s):
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either of the GNU General Public License Version 2 or later (the "GPL"),
28 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #include "mozilla/Util.h"
41 :
42 : #include "jsversion.h"
43 :
44 : #if JS_HAS_XDR
45 :
46 : #include <string.h>
47 : #include "jstypes.h"
48 : #include "jsutil.h"
49 : #include "jsdhash.h"
50 : #include "jsprf.h"
51 : #include "jsapi.h"
52 : #include "jscntxt.h"
53 : #include "jsnum.h"
54 : #include "jsscript.h" /* js_XDRScript */
55 : #include "jsstr.h"
56 : #include "jsxdrapi.h"
57 : #include "vm/Debugger.h"
58 :
59 : #include "jsobjinlines.h"
60 :
61 : using namespace mozilla;
62 : using namespace js;
63 :
64 : #ifdef DEBUG
65 : #define DBG(x) x
66 : #else
67 : #define DBG(x) ((void)0)
68 : #endif
69 :
70 : typedef struct JSXDRMemState {
71 : JSXDRState state;
72 : char *base;
73 : uint32_t count;
74 : uint32_t limit;
75 : } JSXDRMemState;
76 :
77 : #define MEM_BLOCK 8192
78 : #define MEM_PRIV(xdr) ((JSXDRMemState *)(xdr))
79 :
80 : #define MEM_BASE(xdr) (MEM_PRIV(xdr)->base)
81 : #define MEM_COUNT(xdr) (MEM_PRIV(xdr)->count)
82 : #define MEM_LIMIT(xdr) (MEM_PRIV(xdr)->limit)
83 :
84 : #define MEM_LEFT(xdr, bytes) \
85 : JS_BEGIN_MACRO \
86 : if ((xdr)->mode == JSXDR_DECODE && \
87 : MEM_COUNT(xdr) + bytes > MEM_LIMIT(xdr)) { \
88 : JS_ReportErrorNumber((xdr)->cx, js_GetErrorMessage, NULL, \
89 : JSMSG_END_OF_DATA); \
90 : return 0; \
91 : } \
92 : JS_END_MACRO
93 :
94 : #define MEM_NEED(xdr, bytes) \
95 : JS_BEGIN_MACRO \
96 : if ((xdr)->mode == JSXDR_ENCODE) { \
97 : if (MEM_LIMIT(xdr) && \
98 : MEM_COUNT(xdr) + bytes > MEM_LIMIT(xdr)) { \
99 : uint32_t limit_ = JS_ROUNDUP(MEM_COUNT(xdr) + bytes, MEM_BLOCK);\
100 : void *data_ = (xdr)->cx->realloc_(MEM_BASE(xdr), limit_); \
101 : if (!data_) \
102 : return 0; \
103 : MEM_BASE(xdr) = (char *) data_; \
104 : MEM_LIMIT(xdr) = limit_; \
105 : } \
106 : } else { \
107 : MEM_LEFT(xdr, bytes); \
108 : } \
109 : JS_END_MACRO
110 :
111 : #define MEM_DATA(xdr) ((void *)(MEM_BASE(xdr) + MEM_COUNT(xdr)))
112 : #define MEM_INCR(xdr,bytes) (MEM_COUNT(xdr) += (bytes))
113 :
114 : static JSBool
115 7118895 : mem_get32(JSXDRState *xdr, uint32_t *lp)
116 : {
117 7118895 : MEM_LEFT(xdr, 4);
118 7118895 : *lp = *(uint32_t *)MEM_DATA(xdr);
119 7118895 : MEM_INCR(xdr, 4);
120 7118895 : return JS_TRUE;
121 : }
122 :
123 : static JSBool
124 19577410 : mem_set32(JSXDRState *xdr, uint32_t *lp)
125 : {
126 19577410 : MEM_NEED(xdr, 4);
127 19577410 : *(uint32_t *)MEM_DATA(xdr) = *lp;
128 19577410 : MEM_INCR(xdr, 4);
129 19577410 : return JS_TRUE;
130 : }
131 :
132 : static JSBool
133 531276 : mem_getbytes(JSXDRState *xdr, char *bytes, uint32_t len)
134 : {
135 531276 : MEM_LEFT(xdr, len);
136 531276 : js_memcpy(bytes, MEM_DATA(xdr), len);
137 531276 : MEM_INCR(xdr, len);
138 531276 : return JS_TRUE;
139 : }
140 :
141 : static JSBool
142 2507486 : mem_setbytes(JSXDRState *xdr, char *bytes, uint32_t len)
143 : {
144 2507486 : MEM_NEED(xdr, len);
145 2507486 : js_memcpy(MEM_DATA(xdr), bytes, len);
146 2507486 : MEM_INCR(xdr, len);
147 2507486 : return JS_TRUE;
148 : }
149 :
150 : static void *
151 11400893 : mem_raw(JSXDRState *xdr, uint32_t len)
152 : {
153 : void *data;
154 11400893 : if (xdr->mode == JSXDR_ENCODE) {
155 8620524 : MEM_NEED(xdr, len);
156 2780369 : } else if (xdr->mode == JSXDR_DECODE) {
157 2780369 : MEM_LEFT(xdr, len);
158 : }
159 11400893 : data = MEM_DATA(xdr);
160 11400893 : MEM_INCR(xdr, len);
161 11400893 : return data;
162 : }
163 :
164 : static JSBool
165 447490 : mem_seek(JSXDRState *xdr, int32_t offset, JSXDRWhence whence)
166 : {
167 447490 : switch (whence) {
168 : case JSXDR_SEEK_CUR:
169 447490 : if ((int32_t)MEM_COUNT(xdr) + offset < 0) {
170 : JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
171 0 : JSMSG_SEEK_BEYOND_START);
172 0 : return JS_FALSE;
173 : }
174 447490 : if (offset > 0)
175 447490 : MEM_NEED(xdr, offset);
176 447490 : MEM_COUNT(xdr) += offset;
177 447490 : return JS_TRUE;
178 : case JSXDR_SEEK_SET:
179 0 : if (offset < 0) {
180 : JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
181 0 : JSMSG_SEEK_BEYOND_START);
182 0 : return JS_FALSE;
183 : }
184 0 : if (xdr->mode == JSXDR_ENCODE) {
185 0 : if ((uint32_t)offset > MEM_COUNT(xdr))
186 0 : MEM_NEED(xdr, offset - MEM_COUNT(xdr));
187 0 : MEM_COUNT(xdr) = offset;
188 : } else {
189 0 : if ((uint32_t)offset > MEM_LIMIT(xdr)) {
190 : JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
191 0 : JSMSG_SEEK_BEYOND_END);
192 0 : return JS_FALSE;
193 : }
194 0 : MEM_COUNT(xdr) = offset;
195 : }
196 0 : return JS_TRUE;
197 : case JSXDR_SEEK_END:
198 0 : if (offset >= 0 ||
199 : xdr->mode == JSXDR_ENCODE ||
200 : (int32_t)MEM_LIMIT(xdr) + offset < 0) {
201 : JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
202 0 : JSMSG_END_SEEK);
203 0 : return JS_FALSE;
204 : }
205 0 : MEM_COUNT(xdr) = MEM_LIMIT(xdr) + offset;
206 0 : return JS_TRUE;
207 : default: {
208 : char numBuf[12];
209 0 : JS_snprintf(numBuf, sizeof numBuf, "%d", whence);
210 : JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
211 0 : JSMSG_WHITHER_WHENCE, numBuf);
212 0 : return JS_FALSE;
213 : }
214 : }
215 : }
216 :
217 : static uint32_t
218 1908693 : mem_tell(JSXDRState *xdr)
219 : {
220 1908693 : return MEM_COUNT(xdr);
221 : }
222 :
223 : static void
224 12617 : mem_finalize(JSXDRState *xdr)
225 : {
226 12617 : xdr->cx->free_(MEM_BASE(xdr));
227 12617 : }
228 :
229 : static JSXDROps xdrmem_ops = {
230 : mem_get32, mem_set32, mem_getbytes, mem_setbytes,
231 : mem_raw, mem_seek, mem_tell, mem_finalize
232 : };
233 :
234 : JS_PUBLIC_API(void)
235 12617 : JS_XDRInitBase(JSXDRState *xdr, JSXDRMode mode, JSContext *cx)
236 : {
237 12617 : xdr->mode = mode;
238 12617 : xdr->cx = cx;
239 12617 : xdr->userdata = NULL;
240 12617 : xdr->sharedFilename = NULL;
241 12617 : xdr->principals = NULL;
242 12617 : xdr->originPrincipals = NULL;
243 12617 : }
244 :
245 : JS_PUBLIC_API(JSXDRState *)
246 12617 : JS_XDRNewMem(JSContext *cx, JSXDRMode mode)
247 : {
248 12617 : JSXDRState *xdr = (JSXDRState *) cx->malloc_(sizeof(JSXDRMemState));
249 12617 : if (!xdr)
250 0 : return NULL;
251 12617 : JS_XDRInitBase(xdr, mode, cx);
252 12617 : if (mode == JSXDR_ENCODE) {
253 9675 : if (!(MEM_BASE(xdr) = (char *) cx->malloc_(MEM_BLOCK))) {
254 0 : cx->free_(xdr);
255 0 : return NULL;
256 : }
257 : } else {
258 : /* XXXbe ok, so better not deref MEM_BASE(xdr) if not ENCODE */
259 2942 : MEM_BASE(xdr) = NULL;
260 : }
261 12617 : xdr->ops = &xdrmem_ops;
262 12617 : MEM_COUNT(xdr) = 0;
263 12617 : MEM_LIMIT(xdr) = MEM_BLOCK;
264 12617 : return xdr;
265 : }
266 :
267 : JS_PUBLIC_API(void *)
268 18334 : JS_XDRMemGetData(JSXDRState *xdr, uint32_t *lp)
269 : {
270 18334 : if (xdr->ops != &xdrmem_ops)
271 0 : return NULL;
272 18334 : *lp = MEM_COUNT(xdr);
273 18334 : return MEM_BASE(xdr);
274 : }
275 :
276 : JS_PUBLIC_API(void)
277 6505 : JS_XDRMemSetData(JSXDRState *xdr, void *data, uint32_t len)
278 : {
279 6505 : if (xdr->ops != &xdrmem_ops)
280 0 : return;
281 6505 : MEM_LIMIT(xdr) = len;
282 6505 : MEM_BASE(xdr) = (char *) data;
283 6505 : MEM_COUNT(xdr) = 0;
284 : }
285 :
286 : JS_PUBLIC_API(uint32_t)
287 642 : JS_XDRMemDataLeft(JSXDRState *xdr)
288 : {
289 642 : if (xdr->ops != &xdrmem_ops)
290 0 : return 0;
291 642 : return MEM_LIMIT(xdr) - MEM_COUNT(xdr);
292 : }
293 :
294 : JS_PUBLIC_API(void)
295 7375 : JS_XDRMemResetData(JSXDRState *xdr)
296 : {
297 7375 : if (xdr->ops != &xdrmem_ops)
298 0 : return;
299 7375 : MEM_COUNT(xdr) = 0;
300 : }
301 :
302 : JS_PUBLIC_API(void)
303 12617 : JS_XDRDestroy(JSXDRState *xdr)
304 : {
305 12617 : JSContext *cx = xdr->cx;
306 12617 : xdr->ops->finalize(xdr);
307 12617 : cx->free_(xdr);
308 12617 : }
309 :
310 : JS_PUBLIC_API(JSBool)
311 8059 : JS_XDRUint8(JSXDRState *xdr, uint8_t *b)
312 : {
313 8059 : uint32_t l = *b;
314 8059 : if (!JS_XDRUint32(xdr, &l))
315 0 : return JS_FALSE;
316 8059 : *b = (uint8_t) l;
317 8059 : return JS_TRUE;
318 : }
319 :
320 : JS_PUBLIC_API(JSBool)
321 0 : JS_XDRUint16(JSXDRState *xdr, uint16_t *s)
322 : {
323 0 : uint32_t l = *s;
324 0 : if (!JS_XDRUint32(xdr, &l))
325 0 : return JS_FALSE;
326 0 : *s = (uint16_t) l;
327 0 : return JS_TRUE;
328 : }
329 :
330 : JS_PUBLIC_API(JSBool)
331 26696305 : JS_XDRUint32(JSXDRState *xdr, uint32_t *lp)
332 : {
333 26696305 : JSBool ok = JS_TRUE;
334 26696305 : if (xdr->mode == JSXDR_ENCODE) {
335 19577410 : uint32_t xl = JSXDR_SWAB32(*lp);
336 19577410 : ok = xdr->ops->set32(xdr, &xl);
337 7118895 : } else if (xdr->mode == JSXDR_DECODE) {
338 7118895 : ok = xdr->ops->get32(xdr, lp);
339 7118895 : *lp = JSXDR_SWAB32(*lp);
340 : }
341 26696305 : return ok;
342 : }
343 :
344 : JS_PUBLIC_API(JSBool)
345 1908693 : JS_XDRBytes(JSXDRState *xdr, char *bytes, uint32_t len)
346 : {
347 : uint32_t padlen;
348 : static char padbuf[JSXDR_ALIGN-1];
349 :
350 1908693 : if (xdr->mode == JSXDR_ENCODE) {
351 1377417 : if (!xdr->ops->setbytes(xdr, bytes, len))
352 0 : return JS_FALSE;
353 : } else {
354 531276 : if (!xdr->ops->getbytes(xdr, bytes, len))
355 0 : return JS_FALSE;
356 : }
357 1908693 : len = xdr->ops->tell(xdr);
358 1908693 : if (len % JSXDR_ALIGN) {
359 1577559 : padlen = JSXDR_ALIGN - (len % JSXDR_ALIGN);
360 1577559 : if (xdr->mode == JSXDR_ENCODE) {
361 1130069 : if (!xdr->ops->setbytes(xdr, padbuf, padlen))
362 0 : return JS_FALSE;
363 : } else {
364 447490 : if (!xdr->ops->seek(xdr, padlen, JSXDR_SEEK_CUR))
365 0 : return JS_FALSE;
366 : }
367 : }
368 1908693 : return JS_TRUE;
369 : }
370 :
371 : /**
372 : * Convert between a C string and the XDR representation:
373 : * leading 32-bit count, then counted vector of chars,
374 : * then possibly \0 padding to multiple of 4.
375 : */
376 : JS_PUBLIC_API(JSBool)
377 636231 : JS_XDRCString(JSXDRState *xdr, char **sp)
378 : {
379 : uint32_t len;
380 :
381 636231 : if (xdr->mode == JSXDR_ENCODE)
382 459139 : len = strlen(*sp);
383 636231 : JS_XDRUint32(xdr, &len);
384 636231 : if (xdr->mode == JSXDR_DECODE) {
385 177092 : if (!(*sp = (char *) xdr->cx->malloc_(len + 1)))
386 0 : return JS_FALSE;
387 : }
388 636231 : if (!JS_XDRBytes(xdr, *sp, len)) {
389 0 : if (xdr->mode == JSXDR_DECODE)
390 0 : xdr->cx->free_(*sp);
391 0 : return JS_FALSE;
392 : }
393 636231 : if (xdr->mode == JSXDR_DECODE) {
394 177092 : (*sp)[len] = '\0';
395 : }
396 636231 : return JS_TRUE;
397 : }
398 :
399 : static JSBool
400 11400893 : XDRChars(JSXDRState *xdr, jschar *chars, uint32_t nchars)
401 : {
402 : uint32_t i, padlen, nbytes;
403 : jschar *raw;
404 :
405 11400893 : nbytes = nchars * sizeof(jschar);
406 11400893 : padlen = nbytes % JSXDR_ALIGN;
407 11400893 : if (padlen) {
408 5359204 : padlen = JSXDR_ALIGN - padlen;
409 5359204 : nbytes += padlen;
410 : }
411 11400893 : if (!(raw = (jschar *) xdr->ops->raw(xdr, nbytes)))
412 0 : return JS_FALSE;
413 11400893 : if (xdr->mode == JSXDR_ENCODE) {
414 328302569 : for (i = 0; i != nchars; i++)
415 319682045 : raw[i] = JSXDR_SWAB16(chars[i]);
416 8620524 : if (padlen)
417 4029673 : memset((char *)raw + nbytes - padlen, 0, padlen);
418 2780369 : } else if (xdr->mode == JSXDR_DECODE) {
419 41065098 : for (i = 0; i != nchars; i++)
420 38284729 : chars[i] = JSXDR_SWAB16(raw[i]);
421 : }
422 11400893 : return JS_TRUE;
423 : }
424 :
425 : /*
426 : * Convert between a JS (Unicode) string and the XDR representation.
427 : */
428 : JS_PUBLIC_API(JSBool)
429 8622350 : JS_XDRString(JSXDRState *xdr, JSString **strp)
430 : {
431 : uint32_t nchars;
432 : jschar *chars;
433 :
434 8622350 : if (xdr->mode == JSXDR_ENCODE)
435 8620524 : nchars = (*strp)->length();
436 8622350 : if (!JS_XDRUint32(xdr, &nchars))
437 0 : return JS_FALSE;
438 :
439 8622350 : if (xdr->mode == JSXDR_DECODE)
440 1826 : chars = (jschar *) xdr->cx->malloc_((nchars + 1) * sizeof(jschar));
441 : else
442 8620524 : chars = const_cast<jschar *>((*strp)->getChars(xdr->cx));
443 8622350 : if (!chars)
444 0 : return JS_FALSE;
445 :
446 8622350 : if (!XDRChars(xdr, chars, nchars))
447 0 : goto bad;
448 8622350 : if (xdr->mode == JSXDR_DECODE) {
449 1826 : chars[nchars] = 0;
450 1826 : *strp = JS_NewUCString(xdr->cx, chars, nchars);
451 1826 : if (!*strp)
452 0 : goto bad;
453 : }
454 8622350 : return JS_TRUE;
455 :
456 : bad:
457 0 : if (xdr->mode == JSXDR_DECODE)
458 0 : xdr->cx->free_(chars);
459 0 : return JS_FALSE;
460 : }
461 :
462 : JS_PUBLIC_API(JSBool)
463 0 : JS_XDRStringOrNull(JSXDRState *xdr, JSString **strp)
464 : {
465 0 : uint32_t null = (*strp == NULL);
466 0 : if (!JS_XDRUint32(xdr, &null))
467 0 : return JS_FALSE;
468 0 : if (null) {
469 0 : *strp = NULL;
470 0 : return JS_TRUE;
471 : }
472 0 : return JS_XDRString(xdr, strp);
473 : }
474 :
475 : JS_PUBLIC_API(JSBool)
476 975 : JS_XDRDouble(JSXDRState *xdr, double *dp)
477 : {
478 : jsdpun u;
479 :
480 975 : u.d = (xdr->mode == JSXDR_ENCODE) ? *dp : 0.0;
481 975 : if (!JS_XDRUint32(xdr, &u.s.lo) || !JS_XDRUint32(xdr, &u.s.hi))
482 0 : return false;
483 975 : if (xdr->mode == JSXDR_DECODE)
484 0 : *dp = u.d;
485 975 : return true;
486 : }
487 :
488 : extern JSBool
489 11375147 : js_XDRAtom(JSXDRState *xdr, JSAtom **atomp)
490 : {
491 : JSString *str;
492 : uint32_t nchars;
493 : JSAtom *atom;
494 : JSContext *cx;
495 : jschar *chars;
496 : jschar stackChars[256];
497 :
498 11375147 : if (xdr->mode == JSXDR_ENCODE) {
499 8596604 : str = *atomp;
500 8596604 : return JS_XDRString(xdr, &str);
501 : }
502 :
503 : /*
504 : * Inline JS_XDRString when decoding to avoid JSString allocation
505 : * for already existing atoms. See bug 321985.
506 : */
507 2778543 : if (!JS_XDRUint32(xdr, &nchars))
508 0 : return JS_FALSE;
509 2778543 : atom = NULL;
510 2778543 : cx = xdr->cx;
511 2778543 : if (nchars <= ArrayLength(stackChars)) {
512 2775067 : chars = stackChars;
513 : } else {
514 : /*
515 : * This is very uncommon. Don't use the tempLifoAlloc arena for this as
516 : * most allocations here will be bigger than tempLifoAlloc's default
517 : * chunk size.
518 : */
519 3476 : chars = (jschar *) cx->malloc_(nchars * sizeof(jschar));
520 3476 : if (!chars)
521 0 : return JS_FALSE;
522 : }
523 :
524 2778543 : if (XDRChars(xdr, chars, nchars))
525 2778543 : atom = js_AtomizeChars(cx, chars, nchars);
526 2778543 : if (chars != stackChars)
527 3476 : cx->free_(chars);
528 :
529 2778543 : if (!atom)
530 0 : return JS_FALSE;
531 2778543 : *atomp = atom;
532 2778543 : return JS_TRUE;
533 : }
534 :
535 : static bool
536 8059 : XDRPrincipals(JSXDRState *xdr)
537 : {
538 8059 : const uint8_t HAS_PRINCIPALS = 1;
539 8059 : const uint8_t HAS_ORIGIN = 2;
540 :
541 8059 : uint8_t flags = 0;
542 8059 : if (xdr->mode == JSXDR_ENCODE) {
543 7396 : if (xdr->principals)
544 7384 : flags |= HAS_PRINCIPALS;
545 :
546 : /*
547 : * For the common case when principals == originPrincipals we want to
548 : * avoid serializing the same principal twice. As originPrincipals are
549 : * normalized and principals imply originPrincipals we simply set
550 : * HAS_ORIGIN only if originPrincipals is set and different from
551 : * principals. During decoding we re-normalize originPrincipals.
552 : */
553 7396 : JS_ASSERT_IF(xdr->principals, xdr->originPrincipals);
554 7396 : if (xdr->originPrincipals && xdr->originPrincipals != xdr->principals)
555 6 : flags |= HAS_ORIGIN;
556 : }
557 :
558 8059 : if (!JS_XDRUint8(xdr, &flags))
559 0 : return false;
560 :
561 8059 : if (flags & (HAS_PRINCIPALS | HAS_ORIGIN)) {
562 8041 : const JSSecurityCallbacks *scb = JS_GetSecurityCallbacks(xdr->cx->runtime);
563 8041 : if (xdr->mode == JSXDR_DECODE) {
564 654 : if (!scb || !scb->principalsTranscoder) {
565 : JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
566 0 : JSMSG_CANT_DECODE_PRINCIPALS);
567 0 : return false;
568 : }
569 : } else {
570 7387 : JS_ASSERT(scb);
571 7387 : JS_ASSERT(scb->principalsTranscoder);
572 : }
573 :
574 8041 : if (flags & HAS_PRINCIPALS) {
575 8035 : if (!scb->principalsTranscoder(xdr, &xdr->principals))
576 0 : return false;
577 : }
578 :
579 8041 : if (flags & HAS_ORIGIN) {
580 12 : if (!scb->principalsTranscoder(xdr, &xdr->originPrincipals))
581 0 : return false;
582 8029 : } else if (xdr->mode == JSXDR_DECODE && xdr->principals) {
583 648 : xdr->originPrincipals = xdr->principals;
584 648 : JS_HoldPrincipals(xdr->principals);
585 : }
586 : }
587 :
588 8059 : return true;
589 : }
590 :
591 : namespace {
592 :
593 : struct AutoDropXDRPrincipals {
594 : JSXDRState *const xdr;
595 :
596 8059 : AutoDropXDRPrincipals(JSXDRState *xdr)
597 8059 : : xdr(xdr) { }
598 :
599 8059 : ~AutoDropXDRPrincipals() {
600 8059 : if (xdr->mode == JSXDR_DECODE) {
601 663 : if (xdr->principals)
602 651 : JS_DropPrincipals(xdr->cx->runtime, xdr->principals);
603 663 : if (xdr->originPrincipals)
604 654 : JS_DropPrincipals(xdr->cx->runtime, xdr->originPrincipals);
605 : }
606 8059 : xdr->principals = NULL;
607 8059 : xdr->originPrincipals = NULL;
608 8059 : }
609 : };
610 :
611 : } /* namespace anonymous */
612 :
613 : JS_PUBLIC_API(JSBool)
614 12 : JS_XDRFunctionObject(JSXDRState *xdr, JSObject **objp)
615 : {
616 24 : AutoDropXDRPrincipals drop(xdr);
617 12 : if (xdr->mode == JSXDR_ENCODE) {
618 6 : JSScript *script = (*objp)->toFunction()->script();
619 6 : xdr->principals = script->principals;
620 6 : xdr->originPrincipals = script->originPrincipals;
621 : }
622 :
623 12 : return XDRPrincipals(xdr) && XDRFunctionObject(xdr, objp);
624 : }
625 :
626 : JS_PUBLIC_API(JSBool)
627 8047 : JS_XDRScript(JSXDRState *xdr, JSScript **scriptp)
628 : {
629 : JSScript *script;
630 : uint32_t magic;
631 : uint32_t bytecodeVer;
632 8047 : if (xdr->mode == JSXDR_DECODE) {
633 657 : script = NULL;
634 657 : *scriptp = NULL;
635 : } else {
636 7390 : script = *scriptp;
637 7390 : magic = JSXDR_MAGIC_SCRIPT_CURRENT;
638 7390 : bytecodeVer = JSXDR_BYTECODE_VERSION;
639 : }
640 :
641 8047 : if (!JS_XDRUint32(xdr, &magic))
642 0 : return false;
643 8047 : if (!JS_XDRUint32(xdr, &bytecodeVer))
644 0 : return false;
645 :
646 8047 : if (magic != JSXDR_MAGIC_SCRIPT_CURRENT ||
647 : bytecodeVer != JSXDR_BYTECODE_VERSION) {
648 : /* We do not provide binary compatibility with older scripts. */
649 0 : JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL, JSMSG_BAD_SCRIPT_MAGIC);
650 0 : return false;
651 : }
652 :
653 : {
654 16094 : AutoDropXDRPrincipals drop(xdr);
655 8047 : if (xdr->mode == JSXDR_ENCODE) {
656 7390 : xdr->principals = script->principals;
657 7390 : xdr->originPrincipals = script->originPrincipals;
658 : }
659 :
660 8047 : if (!XDRPrincipals(xdr) || !XDRScript(xdr, &script))
661 0 : return false;
662 : }
663 :
664 8047 : if (xdr->mode == JSXDR_DECODE) {
665 657 : JS_ASSERT(!script->compileAndGo);
666 657 : script->globalObject = GetCurrentGlobal(xdr->cx);
667 657 : js_CallNewScriptHook(xdr->cx, script, NULL);
668 657 : Debugger::onNewScript(xdr->cx, script, NULL);
669 657 : *scriptp = script;
670 : }
671 :
672 8047 : return true;
673 : }
674 :
675 : #endif /* JS_HAS_XDR */
|