|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
2 * vim: set ts=8 sts=4 et sw=4 tw=99: |
|
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/. */ |
|
6 |
|
7 #include "vm/Xdr.h" |
|
8 |
|
9 #include <string.h> |
|
10 |
|
11 #include "jsapi.h" |
|
12 #include "jsscript.h" |
|
13 |
|
14 #include "vm/Debugger.h" |
|
15 |
|
16 using namespace js; |
|
17 |
|
18 void |
|
19 XDRBuffer::freeBuffer() |
|
20 { |
|
21 js_free(base); |
|
22 #ifdef DEBUG |
|
23 memset(this, 0xe2, sizeof *this); |
|
24 #endif |
|
25 } |
|
26 |
|
27 bool |
|
28 XDRBuffer::grow(size_t n) |
|
29 { |
|
30 JS_ASSERT(n > size_t(limit - cursor)); |
|
31 |
|
32 const size_t MEM_BLOCK = 8192; |
|
33 size_t offset = cursor - base; |
|
34 size_t newCapacity = JS_ROUNDUP(offset + n, MEM_BLOCK); |
|
35 if (isUint32Overflow(newCapacity)) { |
|
36 JS_ReportErrorNumber(cx(), js_GetErrorMessage, nullptr, JSMSG_TOO_BIG_TO_ENCODE); |
|
37 return false; |
|
38 } |
|
39 |
|
40 void *data = js_realloc(base, newCapacity); |
|
41 if (!data) { |
|
42 js_ReportOutOfMemory(cx()); |
|
43 return false; |
|
44 } |
|
45 base = static_cast<uint8_t *>(data); |
|
46 cursor = base + offset; |
|
47 limit = base + newCapacity; |
|
48 return true; |
|
49 } |
|
50 |
|
51 template<XDRMode mode> |
|
52 bool |
|
53 XDRState<mode>::codeChars(jschar *chars, size_t nchars) |
|
54 { |
|
55 size_t nbytes = nchars * sizeof(jschar); |
|
56 if (mode == XDR_ENCODE) { |
|
57 uint8_t *ptr = buf.write(nbytes); |
|
58 if (!ptr) |
|
59 return false; |
|
60 mozilla::NativeEndian::copyAndSwapToLittleEndian(ptr, chars, nchars); |
|
61 } else { |
|
62 const uint8_t *ptr = buf.read(nbytes); |
|
63 mozilla::NativeEndian::copyAndSwapFromLittleEndian(chars, ptr, nchars); |
|
64 } |
|
65 return true; |
|
66 } |
|
67 |
|
68 template<XDRMode mode> |
|
69 static bool |
|
70 VersionCheck(XDRState<mode> *xdr) |
|
71 { |
|
72 uint32_t bytecodeVer; |
|
73 if (mode == XDR_ENCODE) |
|
74 bytecodeVer = XDR_BYTECODE_VERSION; |
|
75 |
|
76 if (!xdr->codeUint32(&bytecodeVer)) |
|
77 return false; |
|
78 |
|
79 if (mode == XDR_DECODE && bytecodeVer != XDR_BYTECODE_VERSION) { |
|
80 /* We do not provide binary compatibility with older scripts. */ |
|
81 JS_ReportErrorNumber(xdr->cx(), js_GetErrorMessage, nullptr, JSMSG_BAD_SCRIPT_MAGIC); |
|
82 return false; |
|
83 } |
|
84 |
|
85 return true; |
|
86 } |
|
87 |
|
88 template<XDRMode mode> |
|
89 bool |
|
90 XDRState<mode>::codeFunction(MutableHandleObject objp) |
|
91 { |
|
92 if (mode == XDR_DECODE) |
|
93 objp.set(nullptr); |
|
94 |
|
95 if (!VersionCheck(this)) |
|
96 return false; |
|
97 |
|
98 return XDRInterpretedFunction(this, NullPtr(), NullPtr(), objp); |
|
99 } |
|
100 |
|
101 template<XDRMode mode> |
|
102 bool |
|
103 XDRState<mode>::codeScript(MutableHandleScript scriptp) |
|
104 { |
|
105 if (mode == XDR_DECODE) |
|
106 scriptp.set(nullptr); |
|
107 |
|
108 if (!VersionCheck(this)) |
|
109 return false; |
|
110 |
|
111 if (!XDRScript(this, NullPtr(), NullPtr(), NullPtr(), scriptp)) |
|
112 return false; |
|
113 |
|
114 return true; |
|
115 } |
|
116 |
|
117 template<XDRMode mode> |
|
118 bool |
|
119 XDRState<mode>::codeConstValue(MutableHandleValue vp) |
|
120 { |
|
121 return XDRScriptConst(this, vp); |
|
122 } |
|
123 |
|
124 XDRDecoder::XDRDecoder(JSContext *cx, const void *data, uint32_t length, |
|
125 JSPrincipals *originPrincipals) |
|
126 : XDRState<XDR_DECODE>(cx) |
|
127 { |
|
128 buf.setData(data, length); |
|
129 this->originPrincipals_ = originPrincipals; |
|
130 } |
|
131 |
|
132 template class js::XDRState<XDR_ENCODE>; |
|
133 template class js::XDRState<XDR_DECODE>; |