CVSROOT: /sources/gnash Module name: gnash Changes by: Chad Musick <cmusick> 07/10/07 03:19:48
Modified files: . : ChangeLog Added files: server/vm : CodeStream.h Log message: A class for reading ActionScript 3 opcodes and stream information. CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.4559&r2=1.4560 http://cvs.savannah.gnu.org/viewcvs/gnash/server/vm/CodeStream.h?cvsroot=gnash&rev=1.1 Patches: Index: ChangeLog =================================================================== RCS file: /sources/gnash/gnash/ChangeLog,v retrieving revision 1.4559 retrieving revision 1.4560 diff -u -b -r1.4559 -r1.4560 --- ChangeLog 6 Oct 2007 12:00:59 -0000 1.4559 +++ ChangeLog 7 Oct 2007 03:19:48 -0000 1.4560 @@ -1,3 +1,8 @@ +2007-10-07 Chad Musick <[EMAIL PROTECTED]> + + * server/vm/CodeStream.h: New file. Complete definition of a stream + for safely reading code, with necessary reader functions for AS3. + 2007-10-06 Benjamin Wolsey <[EMAIL PROTECTED]> * server/as_value.cpp (to_number): use boost::lexical_cast instead Index: server/vm/CodeStream.h =================================================================== RCS file: server/vm/CodeStream.h diff -N server/vm/CodeStream.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ server/vm/CodeStream.h 7 Oct 2007 03:19:48 -0000 1.1 @@ -0,0 +1,211 @@ +// Copyright (C) 2007 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +#ifndef GNASH_CODESTREAM_H +#define GNASH_CODESTREAM_H + +#include "tu_types.h" +#include <boost/utility.hpp> + +namespace gnash { + +/// The exception which will be thrown by the CodeStream for access +/// violations. +class CodeStreamException { }; + +/// A checked read character array +/// +/// CodeStream provides a safe interface to read various things from a +/// character array of known size. Any attempt to access memory outside +/// of the given array will throw an exception of type CodeStreamException +class CodeStream : private boost::noncopyable +{ +public: + /// Construct a CodeStream + /// + /// @param pStart + /// The beginning of the character array + /// + /// @param length + /// The length of the array. Memory in [pStart, pStart + length) may + /// be accessed. It is not an error to send a length of 0. + /// + /// @param own + /// If true, the given memory will be copied. Otherwise, the caller + /// retains ownership and should not delete the memory before this + /// is invalid. + CodeStream(const char *pStart, std::size_t length, bool own = false) : + mRaw(pStart), mRawEnd(pStart + length), mEnd(pStart + length), + mOwn(false) + { + if (own && length > 0) + { + mCurrent = mRaw = new char[length]; + memcpy(const_cast<char*>(mRaw), pStart, length); + mRawEnd = mEnd = mRaw + length; + mOwn = true; + } + } + + /// Destruct a CodeStream + /// + /// If the stream owns the memory, it will destroy it. + ~CodeStream() + { if (mOwn) delete [] mRaw; } + + /// Read a variable length encoded 32 bit unsigned integer + uint32_t read_V32() + { + if (mCurrent == mEnd) throw CodeStreamException(); + + // We can do an unchecked read in these cases. + if (mEnd - mCurrent > 4 || !(*(mEnd - 1) & 0x80)) + { + uint32_t result = *mCurrent++; + if (!(result & 0x00000080)) return result; + result = (result & 0x0000007F) | *mCurrent++ << 7; + if (!(result & 0x00004000)) return result; + result = (result & 0x00003FFF) | *mCurrent++ << 14; + if (!(result & 0x00200000)) return result; + result = (result & 0x001FFFFF) | *mCurrent++ << 21; + if (!(result & 0x10000000)) return result; + return (result & 0x0FFFFFFF) | *mCurrent++ << 28; + } + uint32_t result = *mCurrent++; + if (!(result & 0x00000080)) return result; + if (mCurrent == mEnd) throw CodeStreamException(); + result = (result & 0x0000007F) | *mCurrent++ << 7; + if (!(result & 0x00004000)) return result; + if (mCurrent == mEnd) throw CodeStreamException(); + result = (result & 0x00003FFF) | *mCurrent++ << 14; + if (!(result & 0x00200000)) return result; + if (mCurrent == mEnd) throw CodeStreamException(); + result = (result & 0x001FFFFF) | *mCurrent++ << 21; + if (!(result & 0x10000000)) return result; + if (mCurrent == mEnd) throw CodeStreamException(); + return (result & 0x0FFFFFFF) | *mCurrent++ << 28; + } + + /// Read an opcode for ActionScript 3 + uint8_t read_as3op() + { + if (mCurrent == mEnd) + return 0; + return static_cast<uint8_t> (*mCurrent++); + } + + /// Provide the offset into the stream of the current position. Can be + /// used for seeking. + std::size_t tell() + { return mCurrent - mRaw; } + + /// Change the current position by a relative value. + void seekBy(int change) + { + if (change > 0 && change > (mEnd - mCurrent) || + change < 0 && -change > (mCurrent - mRaw)) + throw CodeStreamException(); + mCurrent += change; + } + + /// Set the current position to an absolute value (relative to the start) + void seekTo(unsigned int set) + { + if (set > static_cast<unsigned int> (mEnd - mRaw)) + throw CodeStreamException(); + mCurrent = mRaw + set; + } + + /// Read a signed integer encoded in 24 bits. + int32_t read_S24() + { + if (mEnd - mCurrent < 3) + throw CodeStreamException(); + int result = *mCurrent++ + (*mCurrent++ << 8) + (*mCurrent ++ << 16); + if (result & (1 << 23)) // Negative result, adjust appropriately. + result = -(result & ~(1 << 23)); + return static_cast<int32_t>(result); + } + + /// Read a signed 8-bit character. + int8_t read_s8() + { + if (mCurrent == mEnd) + throw CodeStreamException(); + return static_cast<int8_t> (*mCurrent++); + } + + /// Read an unsigned 8-bit character. + uint8_t read_u8() + { + if (mCurrent == mEnd) + throw CodeStreamException(); + return static_cast<uint8_t> (*mCurrent++); + } + + /// Set a stop at position bytes from the start. This becomes the new + /// effective end of the code stream, but the end may be unstopped or + /// set to different length. In no case can the end be set to a point + /// beyond the original end of the stream. + void set_end(unsigned int position) + { + if (position > static_cast<unsigned int>(mRawEnd - mRaw)) + throw CodeStreamException(); + mEnd = mRaw + position; + if (mCurrent > mEnd) + mCurrent = mEnd; + } + + /// Unset any stop placed on the stream. + void unset_end() + { mEnd = mRawEnd; } + + /// Same as read_V32(), but doesn't bother with the arithmetic for + /// calculating the value. + void skip_V32() + { + if (mCurrent == mEnd) throw CodeStreamException(); + + // We can do an unchecked read in these cases. + if (mEnd - mCurrent > 4 || !(*(mEnd - 1) & 0x80)) + { + // shortcut evalution is mandated as standard. + if ((*mCurrent++ & 0x80) && (*mCurrent++ & 0x80) && (*mCurrent++ &0x80) + && (*mCurrent++ & 0x80) && (*mCurrent++ & 0x80)) + return; + return; + } + if (!(*mCurrent++ & 0x80)) return; + if (mCurrent == mEnd) throw CodeStreamException(); + if (!(*mCurrent++ & 0x80)) return; + if (mCurrent == mEnd) throw CodeStreamException(); + if (!(*mCurrent++ & 0x80)) return; + if (mCurrent == mEnd) throw CodeStreamException(); + if (!(*mCurrent++ & 0x80)) return; + if (mCurrent == mEnd) throw CodeStreamException(); + ++mCurrent; + } + +private: + const char *mRaw; // Nobody may write into this, and we handle all access. + const char *mRawEnd; // We own the memory in [mRaw, mRawEnd) + const char *mEnd; // We may not read this or beyond. + const char *mCurrent; // Our current read pointer. + bool mOwn; // Do we own the memory? +}; + +} // namespace gnash +#endif /* GNASH_CODESTREAM_H */ _______________________________________________ Gnash-commit mailing list Gnash-commit@gnu.org http://lists.gnu.org/mailman/listinfo/gnash-commit