Bug Summary

File:platform/mac/avmshell/../../../core/DataIO.cpp
Location:line 148, column 9
Description:Array access (from variable 'buffer') results in a null pointer dereference

Annotated Source Code

1/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
2/* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
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 [Open Source Virtual Machine.].
17 *
18 * The Initial Developer of the Original Code is
19 * Adobe System Incorporated.
20 * Portions created by the Initial Developer are Copyright (C) 2004-2006
21 * the Initial Developer. All Rights Reserved.
22 *
23 * Contributor(s):
24 * Adobe AS3 Team
25 *
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * 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
41#include "avmplus.h"
42
43namespace avmplus
44{
45 //
46 // DataIOBase
47 //
48
49 void DataIOBase::ThrowEOFError()
50 {
51 toplevel()->throwEOFError(kEOFError);
52 }
53
54 void DataIOBase::ThrowMemoryError()
55 {
56 toplevel()->throwMemoryError(kOutOfMemoryError);
57 }
58
59 void DataIOBase::ThrowRangeError()
60 {
61 toplevel()->throwRangeError(kParamRangeError);
62 }
63
64 //
65 // DataInput
66 //
67
68 boolbool DataInput::ReadBoolean()
69 {
70 uint8_t value;
71 Read(&value, 1);
72 return value != 0;
73 }
74
75 uint8_t DataInput::ReadU8()
76 {
77 uint8_t value;
78 Read(&value, 1);
79 return value;
80 }
81
82 uint16_t DataInput::ReadU16()
83 {
84 union {
85 uint8_t b[2];
86 uint16_t u;
87 };
88 Read(b, 2);
89 ConvertU16(u);
90 return u;
91 }
92
93 uint32_t DataInput::ReadU32()
94 {
95 union {
96 uint8_t b[4];
97 uint32_t u;
98 };
99 Read(b, 4);
100 ConvertU32(u);
101 return u;
102 }
103
104 float DataInput::ReadFloat()
105 {
106 union {
107 uint8_t b[4];
108 uint32_t u;
109 float f;
110 };
111 Read(b, 4);
112 ConvertU32(u);
113 return f;
114 }
115
116 double DataInput::ReadDouble()
117 {
118 union {
119 uint8_t b[8];
120 uint64_t u;
121 double d;
122 };
123 Read(b, 8);
124 ConvertD64(u);
125 return d;
126 }
127
128 String* DataInput::ReadMultiByte(uint32_t length, String* charset)
129 {
130 CheckEOF(length);
131
132 Toplevel* toplevel = this->toplevel();
133 uint32_t codepage = toplevel->charsetToCodepage(charset);
134 String* result = toplevel->readMultiByte(codepage, length, this);
135 return result;
136 }
137
138 String* DataInput::ReadUTFBytes(uint32_t length)
139 {
140 CheckEOF(length);
141
142 char *buffer = mmfx_new_array_opt( char, length+1, MMgc::kCanFail )::MMgcConstructTaggedArray((char*)__null, length+1, MMgc::kCanFail
)
;
143 if (!buffer) {
1
Taking true branch
144 ThrowMemoryError();
145 }
146
147 Read(buffer, length);
148 buffer[length] = 0;
2
Array access (from variable 'buffer') results in a null pointer dereference
149
150 // Since this is supposed to read UTF8 into a string, it really should ignore the UTF8 BOM that
151 // might reasonably occur at the head of the data.
152 char* utf8chars = buffer;
153 if (length >= 3 && (unsigned char)buffer[0] == 0xEF && (unsigned char)buffer[1] == 0xBB && (unsigned char)buffer[2] == 0xBF)
154 {
155 utf8chars += 3;
156 }
157
158 String* out = toplevel()->core()->newStringUTF8(utf8chars);
159 mmfx_delete_array( buffer )::MMgcDestructTaggedArrayChecked(buffer);
160
161 return out;
162 }
163
164 String* DataInput::ReadUTF()
165 {
166 return ReadUTFBytes(ReadU16());
167 }
168
169 void DataInput::ReadByteArray(ByteArray& buffer,
170 uint32_t offset,
171 uint32_t count)
172 {
173 uint32_t available = Available();
174
175 if (count == 0) {
176 count = available;
177 }
178
179 if (count > available) {
180 ThrowEOFError();
181 }
182
183 // check for 32 bit overflow
184 uint64_t total = (uint64_t)offset + (uint64_t)count;
185 if (total != (uint64_t)(offset + count))
186 ThrowRangeError();
187
188 // Grow the buffer if necessary
189 if (offset + count >= buffer.GetLength()) {
190 buffer.SetLength(offset + count);
191 }
192
193 Read(buffer.GetWritableBuffer() + offset, count);
194 }
195
196 void DataInput::CheckEOF(uint32_t count)
197 {
198 if (Available() < count) {
199 ThrowEOFError();
200 }
201 }
202
203 Atom DataInput::ReadObject()
204 {
205 Toplevel* toplevel = this->toplevel();
206 return toplevel->readObject(GetObjectEncoding(), this);
207 }
208
209 //
210 // DataOutput
211 //
212
213 void DataOutput::WriteBoolean(boolbool value)
214 {
215 WriteU8(value ? 1 : 0);
216 }
217
218 void DataOutput::WriteU8(uint8_t value)
219 {
220 Write(&value, 1);
221 }
222
223 void DataOutput::WriteU16(uint16_t value)
224 {
225 union {
226 uint8_t b[2];
227 uint16_t u;
228 };
229 u = value;
230 ConvertU16(u);
231 Write(b, 2);
232 }
233
234 void DataOutput::WriteU32(uint32_t value)
235 {
236 union {
237 uint8_t b[4];
238 uint32_t u;
239 };
240 u = value;
241 ConvertU32(u);
242 Write(b, 4);
243 }
244
245 void DataOutput::WriteFloat(float value)
246 {
247 union {
248 uint8_t b[4];
249 uint32_t u;
250 float f;
251 };
252 f = value;
253 ConvertU32(u);
254 Write(b, 4);
255 }
256
257 void DataOutput::WriteDouble(double value)
258 {
259 union {
260 uint8_t b[8];
261 uint64_t u;
262 double d;
263 };
264 d = value;
265 ConvertD64(u);
266 Write(b, 8);
267 }
268
269 void DataOutput::WriteMultiByte(String* str, String* charset)
270 {
271 Toplevel* toplevel = this->toplevel();
272 uint32_t codepage = toplevel->charsetToCodepage(charset);
273 toplevel->writeMultiByte(codepage, str, this);
274 }
275
276 void DataOutput::WriteUTF(String *str)
277 {
278 StUTF8String utf8(str);
279 uint32_t length = utf8.length();
280 if (length > 65535) {
281 ThrowRangeError();
282 }
283 WriteU16((uint16_t)length);
284 Write(utf8.c_str(), length*sizeof(char));
285 }
286
287 void DataOutput::WriteUTFBytes(String *str)
288 {
289 StUTF8String utf8(str);
290 int len = utf8.length();
291 Write(utf8.c_str(), len*sizeof(char));
292 }
293
294 void DataOutput::WriteByteArray(ByteArray& buffer,
295 uint32_t offset,
296 uint32_t count)
297 {
298 if (offset > buffer.GetLength())
299 offset = buffer.GetLength();
300
301 if (count == 0) {
302 count = buffer.GetLength()-offset;
303 }
304
305 if (count > buffer.GetLength()-offset) {
306 ThrowRangeError();
307 }
308
309 if (count > 0) {
310 Write(buffer.GetReadableBuffer()+offset, count);
311 }
312 }
313
314 void DataOutput::WriteObject(Atom atom)
315 {
316 Toplevel* toplevel = this->toplevel();
317 toplevel->writeObject(GetObjectEncoding(), this, atom);
318 }
319}
320
321