1 // stream.h - SWF stream reading class, for Gnash
2 //
3 //   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
4 //   Free Software Foundation, Inc
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19 
20 #ifndef GNASH_STREAM_H
21 #define GNASH_STREAM_H
22 
23 #include "SWF.h"
24 #include "dsodefs.h" // still neded ?
25 #include "GnashException.h"
26 
27 #include <string>
28 #include <sstream>
29 #include <vector> // for composition
30 #include <cstdint> // for boost::?int??_t
31 
32 // Define the following macro if you want to want Gnash parser
33 // to assume the underlying SWF is well-formed. It would make
34 // parsing faster, but might result in horrible behaviour with
35 // malformed SWFs (like taking up all system memory, keeping
36 // CPU busy for a long long time, or simply corrupting memory)
37 //
38 // This might be eventually set by a --disable-swf-checks or similar
39 // configure switch...
40 //
41 //#define GNASH_TRUST_SWF_INPUT
42 
43 namespace gnash {
44 	class IOChannel;
45 }
46 
47 namespace gnash {
48 
49 /// SWF stream wrapper class
50 //
51 /// This class is used for loading variable-length data
52 /// from a stream, and keeping track of SWF tag boundaries.
53 ///
54 /// Provides 'aligned' and 'bitwise' read functions:
55 /// - aligned reads always start on a byte boundary
56 /// - bitwise reads can cross byte boundaries
57 ///
58 class DSOEXPORT SWFStream
59 {
60 public:
61 	SWFStream(IOChannel* input);
62 	~SWFStream();
63 
64 	/// \brief
65 	/// Reads a bit-packed unsigned integer from the stream
66 	/// and returns it.  The given bitcount determines the
67 	/// number of bits to read.
68 	//
69 	/// bitwise read
70 	///
71 	unsigned read_uint(unsigned short bitcount);
72 
73 	/// \brief
74 	/// Reads a single bit off the stream
75 	/// and returns it.
76 	//
77 	/// bitwise read
78 	///
79 	bool read_bit();
80 
81 	/// \brief
82 	/// Reads a bit-packed little-endian signed integer
83 	/// from the stream.  The given bitcount determines the
84 	/// number of bits to read.
85 	//
86 	/// bitwise read
87 	///
88 	int	read_sint(unsigned short bitcount);
89 
90 	/// Read a 16.16 fixed point signed value
91 	//
92 	/// aligned read
93 	///
94 	float	read_fixed();
95 
96 	/// Read a 16.16 fixed point unsigned value
97 	//
98 	/// aligned read
99 	///
100 	float	read_ufixed();
101 
102 	/// Read a 8.8 fixed point unsigned value
103 	//
104 	/// aligned read
105 	///
106 	float   read_short_ufixed();
107 
108 	/// Read a 8.8 fixed point signed value
109 	//
110 	/// aligned read
111 	///
112 	float	read_short_sfixed();
113 
114 	/// Read a 32bit (1:sign 8:exp 23:mantissa) floating point value
115 	//
116 	/// aligned read
117 	///
118 	float	read_long_float();
119 
120 	/// Read a 64-bit double value
121 	//
122 	/// aligned read
123 	///
124 	double read_d64();
125 
126 	/// Consume all bits of current byte
127 	//
128 	/// This method is implicitly called by all 'aligned' reads.
129 	///
130 	/// NOTE:
131 	/// The position returned by tell() won't be changed
132 	/// by calls to this function, altought any subsequent reads
133 	/// will start on next byte. See tell() for more info.
134 	///
align()135 	void	align()
136 	{
137 		m_unused_bits=0;
138 		// m_current_byte = 0; // this is not needed
139 	}
140 
141 	/// Read <count> bytes from the source stream and copy that data to <buf>.
142 	//
143 	/// aligned read
144 	///
145 	unsigned read(char *buf, unsigned count);
146 
147 	/// Read a aligned unsigned 8-bit value from the stream.
148 	//
149 	/// aligned read
150 	///
151 	std::uint8_t  read_u8();
152 
153 	/// Read a aligned signed 8-bit value from the stream.
154 	//
155 	/// aligned read
156 	///
157     std::int8_t read_s8();
158 
159 	/// Read a aligned unsigned 16-bit value from the stream.
160 	//
161 	/// aligned read
162 	///
163 	std::uint16_t read_u16();
164 
165 	/// Read a aligned signed 16-bit value from the stream.
166 	//
167 	/// aligned read
168 	///
169 	std::int16_t  read_s16();
170 
171 	/// Read a aligned unsigned 32-bit value from the stream.
172 	//
173 	/// aligned read
174 	///
175 	std::uint32_t read_u32();
176 
177 	/// \brief
178 	/// Read a aligned signed 32-bit value from the stream.
179 	//
180 	/// aligned read
181 	///
182 	std::int32_t  read_s32();
183 
184 	/// \brief
185 	/// Read a variable length unsigned 32-bit value from the stream.
186 	/// These values continue until either the high bit is not set or
187 	/// until 5 bytes have been read.
188 	//
189 	/// aligned read
190 	///
read_V32()191 	std::uint32_t read_V32()
192 	{
193         ensureBytes(1);
194 		std::uint32_t res = read_u8();
195 		if (!(res & 0x00000080)) return res;
196 
197         ensureBytes(1);
198 		res = (res & 0x0000007F) | read_u8() << 7;
199 		if (!(res & 0x00004000)) return res;
200 
201         ensureBytes(1);
202 		res = (res & 0x00003FFF) | read_u8() << 14;
203 		if (!(res & 0x00200000)) return res;
204 
205         ensureBytes(1);
206 		res = (res & 0x001FFFFF) | read_u8() << 21;
207 		if (!(res & 0x10000000)) return res;
208 
209         ensureBytes(1);
210 		res = (res & 0x0FFFFFFF) | read_u8() << 28;
211 		return res;
212 	}
213 
214 	/// \brief
215 	/// Skip a variable length unsigned 32-bit value in the stream.
216 	/// This is faster than doing the bitwise arithmetic of full reading.
217 	///
218 	/// aligned read
219 	///
skip_V32()220 	void skip_V32()
221 	{
222         ensureBytes(1);
223 		if (!(read_u8() & 0x80)) return;
224         ensureBytes(1);
225 		if (!(read_u8() & 0x80)) return;
226         ensureBytes(1);
227 		if (!(read_u8() & 0x80)) return;
228         ensureBytes(1);
229 		if (!(read_u8() & 0x80)) return;
230         ensureBytes(1);
231 		static_cast<void> (read_u8());
232 	}
233 
234 	/// \brief
235 	/// Read a length in a byte or three.
236 	//
237 	/// If the byte == 0xff, read the lenght in
238 	/// next two bytes.
239 	///
240 	/// Takes care of integrity check (ensureByte)
241 	///
242 	/// aligned read
243 	///
read_variable_count()244 	unsigned read_variable_count()
245 	{
246 		ensureBytes(1);
247 		unsigned count = read_u8();
248 		if (count == 0xFF)
249 		{
250 			ensureBytes(2);
251 			count = read_u16();
252 		}
253 		return count;
254 	};
255 
256 	/// \brief
257 	/// Reads a null-terminated string from the given file and
258 	/// assigns it to the given std::string, overriding any
259 	/// previous value of it.
260 	///
261 	/// aligned read
262 	///
263 	/// Will throw ParserException if no terminating null is found within
264     /// tag boundaries
265 	void read_string(std::string& to);
266 
267 	/// Reads a sized string into a provided std::string.
268 	//
269 	/// Length of string is read from the first byte.
270 	///
271 	/// @param to
272 	/// 	Output argument. Any previous value will be overriden.
273 	///
274 	/// aligned read
275 	///
276 	/// Will throw ParserException if advertised length crosses tag boundaries
277 	///
278 	void	read_string_with_length(std::string& to);
279 
280 	/// Reads a sized string into a provided std::string.
281 	//
282 	///
283 	/// @param len
284 	///	Length of string to read.
285 	///
286 	/// @param to
287 	/// 	Output argument. Any previous value will be overriden.
288 	///
289 	/// aligned read
290 	///
291 	/// Will throw ParserException if len crosses tag boundaries
292 	///
293 	void	read_string_with_length(unsigned len, std::string& to);
294 
295 	/// Return our current (byte) position in the input stream.
296 	//
297 	/// NOTE:
298 	/// This is not necessarely the byte you'll read on next read.
299 	/// - For bitwise reads the currenty byte will be used only if not
300 	///   completely consumed. See align().
301 	/// - For aligned reads the current byte will not be used
302 	///   (already used)
303 	///
304 	unsigned long tell();
305 
306 	/// Set the file position to the given value (byte aligned)
307 	//
308 	/// If we're scanning a tag, don't allow seeking past
309 	/// the end or before start of it.
310 	///
311 	/// @return true on success, false on failure
312 	/// 	Possible failures:
313 	///	- given position is after end of stream.
314 	///	- given position is after end of current tag, if any.
315 	///	- given position is before start of current tag, if any.
316 	///
317 	bool seek(unsigned long pos);
318 
319 	/// Return the file position of the end of the current tag.
320 	unsigned long get_tag_end_position();
321 
322 	/// Open an SWF tag and return it's type.
323 	//
324 	/// aligned read
325 	///
326 	SWF::TagType	open_tag();
327 
328 	/// Seek to the end of the most-recently-opened tag.
329 	void	close_tag();
330 
331 	/// Discard given number of bytes
332 	//
333 	///
334 	/// @return true on success, false on failure
335 	/// 	Possible failures:
336 	///	- skipping given number of bytes reaches end of stream.
337 	///	- skipping given number of bytes reaches end of
338 	///	  current tag, if any.
339 	///
340 	/// WARNING: alignment is not specified here, the method uses
341 	///          tell() which is known NOT to consider
342 	///          a fully-read byte as already "skipped"
343 	///	     TODO: force alignment and see what happens !!
344 	///
skip_bytes(unsigned num)345 	bool skip_bytes(unsigned num)
346 	{
347 		// there's probably a better way, but
348 		// it's the interface that counts atm
349 		size_t curpos = tell();
350 		return seek(curpos+num);
351 	}
352 
353 	/// Discard all bytes up to end of tag
skip_to_tag_end()354 	void skip_to_tag_end()
355 	{
356 		// seek will call align...
357 		seek(get_tag_end_position());
358 	}
359 
360 	/// \brief
361 	/// Ensure the requested number of bytes are available for an aligned read
362 	/// in the currently opened tag.
363 	//
364 	/// Throws a ParserException on a short count.
365 	/// This method should be called before any attempt to read
366 	/// fields from the SWF.
367 	///
368 	/// NOTE: if GNASH_TRUST_SWF_INPUT is defined this function is a no-op
369 	///
370 	void ensureBytes(unsigned long needed);
371 
372 	/// \brief
373 	/// Ensure the requested number of bits are available for a bitwise read
374 	/// in currently opened tag.
375 	//
376 	/// Throws a ParserException on a short count.
377 	/// This method should be called before any attempt to read
378 	/// bits from the SWF.
379 	///
380 	/// NOTE: if GNASH_TRUST_SWF_INPUT is defined this function is a no-op
381 	///
ensureBits(unsigned long needed)382 	void ensureBits(unsigned long needed)
383 	{
384 #ifndef GNASH_TRUST_SWF_INPUT
385 		if ( _tagBoundsStack.empty() ) return; // not in a tag (should we check file length ?)
386 		unsigned long int bytesLeft = get_tag_end_position() - tell();
387 		unsigned long int bitsLeft = (bytesLeft*8)+m_unused_bits;
388 		if ( bitsLeft < needed )
389 		{
390 			std::stringstream ss;
391 			ss << "premature end of tag: need to read " << needed << " bytes, but only " << bitsLeft << " left in this tag";
392 			throw ParserException(ss.str());
393 		}
394 #endif
395 	}
396 
397 	/// Consume any pending input
398 	//
399 	/// This method is useful to force full consumption
400 	/// of the SWFStream's underlying IOChannel for the
401 	/// cases in which it is a pipe and a writer would
402 	/// hang on it unless someone is reading.
403 	///
404 	/// This method will NOT be called automatically
405 	/// on SWFStream destruction as in the current
406 	/// design SWFStream does NOT own the underlying
407 	/// IOChannel. TODO: rethink about ownership.
408 	///
409 	/// NOTE: the stream position will be updated by
410 	///       this call, so that ::tell will basically
411 	///       return the full input size.
412 	///
413 	void consumeInput();
414 
415 private:
416 
417 	IOChannel*	m_input;
418 	std::uint8_t	m_current_byte;
419 	std::uint8_t	m_unused_bits;
420 
421 	typedef std::pair<unsigned long,unsigned long> TagBoundaries;
422 	// position of start and end of tag
423 	std::vector<TagBoundaries> _tagBoundsStack;
424 };
425 
426 
427 } // namespace gnash
428 
429 
430 #endif // GNASH_STREAM_H
431 
432 
433 // Local Variables:
434 // mode: C++
435 // c-basic-offset: 8
436 // tab-width: 8
437 // indent-tabs-mode: t
438 // End:
439