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 : #include <string.h>
45 : #include "jstypes.h"
46 : #include "jsutil.h"
47 : #include "jsdhash.h"
48 : #include "jsprf.h"
49 : #include "jsapi.h"
50 : #include "jscntxt.h"
51 : #include "jsnum.h"
52 : #include "jsscript.h"
53 : #include "jsstr.h"
54 :
55 : #include "Xdr.h"
56 : #include "Debugger.h"
57 :
58 : #include "jsobjinlines.h"
59 :
60 : using namespace mozilla;
61 : using namespace js;
62 :
63 : namespace js {
64 :
65 : void
66 2390 : XDRBuffer::freeBuffer()
67 : {
68 2390 : Foreground::free_(base);
69 : #ifdef DEBUG
70 2390 : memset(this, 0xe2, sizeof *this);
71 : #endif
72 2390 : }
73 :
74 : bool
75 2390 : XDRBuffer::grow(size_t n)
76 : {
77 2390 : JS_ASSERT(n > size_t(limit - cursor));
78 :
79 2390 : const size_t MEM_BLOCK = 8192;
80 2390 : size_t offset = cursor - base;
81 2390 : size_t newCapacity = JS_ROUNDUP(offset + n, MEM_BLOCK);
82 2390 : if (isUint32Overflow(newCapacity)) {
83 0 : JS_ReportErrorNumber(cx(), js_GetErrorMessage, NULL, JSMSG_TOO_BIG_TO_ENCODE);
84 0 : return false;
85 : }
86 :
87 2390 : void *data = OffTheBooks::realloc_(base, newCapacity);
88 2390 : if (!data) {
89 0 : js_ReportOutOfMemory(cx());
90 0 : return false;
91 : }
92 2390 : base = static_cast<uint8_t *>(data);
93 2390 : cursor = base + offset;
94 2390 : limit = base + newCapacity;
95 2390 : return true;
96 : }
97 :
98 : template<XDRMode mode>
99 : bool
100 : XDRState<mode>::codeChars(jschar *chars, size_t nchars)
101 : {
102 7871 : size_t nbytes = nchars * sizeof(jschar);
103 : if (mode == XDR_ENCODE) {
104 7871 : uint8_t *ptr = buf.write(nbytes);
105 7871 : if (!ptr)
106 0 : return false;
107 : #ifdef IS_LITTLE_ENDIAN
108 7871 : memcpy(ptr, chars, nbytes);
109 : #else
110 : for (size_t i = 0; i != nchars; i++) {
111 : uint16_t tmp = NormalizeByteOrder16(chars[i]);
112 : memcpy(ptr, &tmp, sizeof tmp);
113 : ptr += sizeof tmp;
114 : }
115 : #endif
116 : } else {
117 0 : const uint8_t *ptr = buf.read(nbytes);
118 : #ifdef IS_LITTLE_ENDIAN
119 0 : memcpy(chars, ptr, nbytes);
120 : #else
121 : for (size_t i = 0; i != nchars; i++) {
122 : uint16_t tmp;
123 : memcpy(&tmp, ptr, sizeof tmp);
124 : chars[i] = NormalizeByteOrder16(tmp);
125 : ptr += sizeof tmp;
126 : }
127 : #endif
128 : }
129 7871 : return true;
130 : }
131 :
132 : /*
133 : * Convert between a JS (Unicode) string and the XDR representation.
134 : */
135 : template<XDRMode mode>
136 : bool
137 : XDRState<mode>::codeString(JSString **strp)
138 : {
139 : uint32_t nchars;
140 : jschar *chars;
141 :
142 : if (mode == XDR_ENCODE)
143 7871 : nchars = (*strp)->length();
144 7871 : if (!codeUint32(&nchars))
145 0 : return false;
146 :
147 : if (mode == XDR_DECODE)
148 0 : chars = (jschar *) cx()->malloc_((nchars + 1) * sizeof(jschar));
149 : else
150 7871 : chars = const_cast<jschar *>((*strp)->getChars(cx()));
151 7871 : if (!chars)
152 0 : return false;
153 :
154 7871 : if (!codeChars(chars, nchars))
155 0 : goto bad;
156 : if (mode == XDR_DECODE) {
157 0 : chars[nchars] = 0;
158 0 : *strp = JS_NewUCString(cx(), chars, nchars);
159 0 : if (!*strp)
160 0 : goto bad;
161 : }
162 7871 : return true;
163 :
164 : bad:
165 : if (mode == XDR_DECODE)
166 0 : Foreground::free_(chars);
167 0 : return false;
168 : }
169 :
170 : template<XDRMode mode>
171 : static bool
172 42 : VersionCheck(XDRState<mode> *xdr)
173 : {
174 : uint32_t bytecodeVer;
175 : if (mode == XDR_ENCODE)
176 21 : bytecodeVer = XDR_BYTECODE_VERSION;
177 :
178 42 : if (!xdr->codeUint32(&bytecodeVer))
179 0 : return false;
180 :
181 21 : if (mode == XDR_DECODE && bytecodeVer != XDR_BYTECODE_VERSION) {
182 : /* We do not provide binary compatibility with older scripts. */
183 0 : JS_ReportErrorNumber(xdr->cx(), js_GetErrorMessage, NULL, JSMSG_BAD_SCRIPT_MAGIC);
184 0 : return false;
185 : }
186 :
187 42 : return true;
188 : }
189 :
190 : template<XDRMode mode>
191 : bool
192 : XDRState<mode>::codeFunction(JSObject **objp)
193 : {
194 : if (mode == XDR_DECODE)
195 6 : *objp = NULL;
196 :
197 12 : return VersionCheck(this) && XDRInterpretedFunction(this, objp, NULL);
198 : }
199 :
200 : template<XDRMode mode>
201 : bool
202 : XDRState<mode>::codeScript(JSScript **scriptp)
203 : {
204 : JSScript *script;
205 : if (mode == XDR_DECODE) {
206 15 : script = NULL;
207 15 : *scriptp = NULL;
208 : } else {
209 15 : script = *scriptp;
210 : }
211 :
212 30 : if (!VersionCheck(this) || !XDRScript(this, &script, NULL))
213 0 : return false;
214 :
215 : if (mode == XDR_DECODE) {
216 15 : JS_ASSERT(!script->compileAndGo);
217 15 : script->globalObject = GetCurrentGlobal(cx());
218 15 : js_CallNewScriptHook(cx(), script, NULL);
219 15 : Debugger::onNewScript(cx(), script, NULL);
220 15 : *scriptp = script;
221 : }
222 :
223 30 : return true;
224 : }
225 :
226 2390 : XDRDecoder::XDRDecoder(JSContext *cx, const void *data, uint32_t length,
227 : JSPrincipals *principals, JSPrincipals *originPrincipals)
228 2390 : : XDRState<XDR_DECODE>(cx)
229 : {
230 2390 : buf.setData(data, length);
231 2390 : this->principals = principals;
232 2390 : this->originPrincipals = JSScript::normalizeOriginPrincipals(principals, originPrincipals);
233 2390 : }
234 :
235 : template class XDRState<XDR_ENCODE>;
236 : template class XDRState<XDR_DECODE>;
237 :
238 : } /* namespace js */
239 :
|