CVSROOT: /sources/gnash Module name: gnash Changes by: Sandro Santilli <strk> 07/12/12 23:49:28
Modified files: . : ChangeLog server/parser : button_character_def.cpp button_character_def.h Log message: cleanup parser by splitting DEFINEBUTTON, DEFINEBUTTON2 and DEFINEBUTTONSOUND reading functions. Added a boundary arg to button_record parser to avoid reading out of bounds (with side-effect of reducing seek-back need) CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.5151&r2=1.5152 http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/button_character_def.cpp?cvsroot=gnash&r1=1.19&r2=1.20 http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/button_character_def.h?cvsroot=gnash&r1=1.20&r2=1.21 Patches: Index: ChangeLog =================================================================== RCS file: /sources/gnash/gnash/ChangeLog,v retrieving revision 1.5151 retrieving revision 1.5152 diff -u -b -r1.5151 -r1.5152 --- ChangeLog 12 Dec 2007 22:45:27 -0000 1.5151 +++ ChangeLog 12 Dec 2007 23:49:27 -0000 1.5152 @@ -1,5 +1,13 @@ 2007-12-12 Sandro Santilli <[EMAIL PROTECTED]> + * server/parser/button_character_def.{cpp,h}: cleanup parser by + splitting DEFINEBUTTON, DEFINEBUTTON2 and DEFINEBUTTONSOUND + reading functions. Added a boundary arg to button_record parser + to avoid reading out of bounds (with side-effect of reducing + seek-back need) + +2007-12-12 Sandro Santilli <[EMAIL PROTECTED]> + * testsuite/actionscript.all/System.as: update expected results. * server/swf/tag_loaders.cpp (define_bits_jpeg3_loader): don't read rgb data past alpha_position. Index: server/parser/button_character_def.cpp =================================================================== RCS file: /sources/gnash/gnash/server/parser/button_character_def.cpp,v retrieving revision 1.19 retrieving revision 1.20 diff -u -b -r1.19 -r1.20 --- server/parser/button_character_def.cpp 7 Oct 2007 21:15:59 -0000 1.19 +++ server/parser/button_character_def.cpp 12 Dec 2007 23:49:28 -0000 1.20 @@ -17,7 +17,7 @@ // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // -/* $Id: button_character_def.cpp,v 1.19 2007/10/07 21:15:59 strk Exp $ */ +/* $Id: button_character_def.cpp,v 1.20 2007/12/12 23:49:28 strk Exp $ */ // Based on the public domain work of Thatcher Ulrich <[EMAIL PROTECTED]> 2003 @@ -91,18 +91,34 @@ bool button_record::read(stream* in, int tag_type, - movie_definition* m) + movie_definition* m, unsigned long endPos) { + // caller should check this + assert(in->get_position() < endPos); int flags = in->read_u8(); if (flags == 0) { return false; } - m_hit_test = flags & 8 ? true : false; - m_down = flags & 4 ? true : false; - m_over = flags & 2 ? true : false; - m_up = flags & 1 ? true : false; + // Upper 4 bits are: + // + // ButtonReserved = readBits (f, 2); + // ButtonHasBlendMode = readBits(f, 1); + // ButtonHasFilterList = readBits(f, 1); + // + m_hit_test = flags & (1<<3); // 8 ? true : false; + m_down = flags & (1<<2); // 4 ? true : false; + m_over = flags & (1<<1); // 2 ? true : false; + m_up = flags & (1<<0); // 1 ? true : false; + + if (in->get_position()+2 > endPos) + { + IF_VERBOSE_MALFORMED_SWF( + log_swferror(_(" premature end of button record input stream, can't read character id")); + ); + return false; + } m_character_id = in->read_u16(); // Get character definition now (safer) @@ -122,16 +138,26 @@ { IF_VERBOSE_PARSE( log_parse(_(" button record for states %x contain " - "character %d (%s)"), flags, m_character_id, + "character %d (%s)"), (m_hit_test<<4)+(m_down<<2)+(m_over<<1)+(m_up), m_character_id, typeName(*m_character_def).c_str()); ); } + if (in->get_position()+2 > endPos) + { + IF_VERBOSE_MALFORMED_SWF( + log_swferror(_(" premature end of button record input stream, can't read button layer (depth?)")); + ); + return false; + } m_button_layer = in->read_u16(); + + // TODO: pass available range to button matrix read m_button_matrix.read(in); - if (tag_type == 34) + if (tag_type == SWF::DEFINEBUTTON2) { + // TODO: pass available range to button cxform read m_button_cxform.read_rgba(in); } @@ -202,29 +228,20 @@ ); } - - void -button_character_definition::read(stream* in, int tag_type, movie_definition* m) -// Initialize from the given stream. +button_character_definition::readDefineButton(stream* in, movie_definition* m) { // Character ID has been read already - assert( - tag_type == SWF::DEFINEBUTTON // 7 - || tag_type == SWF::DEFINEBUTTONSOUND // 17 - || tag_type == SWF::DEFINEBUTTON2 // 34 - ); - - if (tag_type == SWF::DEFINEBUTTON) - { // Old button tag. + unsigned long endTagPos = in->get_tag_end_position(); + // Read button character records. for (;;) { button_record r; - if (r.read(in, tag_type, m) == false) + if (r.read(in, SWF::DEFINEBUTTON, m, endTagPos) == false) { // Null record; marks the end of button records. break; @@ -238,50 +255,64 @@ } } + if ( in->get_position() >= endTagPos ) + { + IF_VERBOSE_MALFORMED_SWF( + log_swferror(_("Premature end of DEFINEBUTTON tag, won't read actions")); + ); + return; + } + // Read actions. button_action actions; - actions.read(in, tag_type); + // TODO: pass valid end position to button_action parser + actions.read(in, SWF::DEFINEBUTTON); m_button_actions.push_back(actions); - } - else if (tag_type == SWF::DEFINEBUTTONSOUND) - { - assert(m_sound == NULL); // redefinition button sound is error - m_sound = new button_sound_def(); - IF_VERBOSE_PARSE( - log_parse(_("button sound options: ")); - ); - for (int i = 0; i < 4; i++) - { - button_sound_info& bs = m_sound->m_button_sounds[i]; - bs.m_sound_id = in->read_u16(); - if (bs.m_sound_id > 0) - { - bs.m_sam = m->get_sound_sample(bs.m_sound_id); - if (bs.m_sam == NULL) + + // detect min/max layer number + m_min_layer=0; + m_max_layer=0; + for (unsigned int i=0; i<m_button_records.size(); i++) { -// printf("sound tag not found, sound_id=%d, button state #=%i", bs.sound_id, i); - } - IF_VERBOSE_PARSE( - log_parse("\n sound_id = %d", bs.m_sound_id); - ); - bs.m_sound_style.read(in); - } - } + int this_layer = m_button_records[i].m_button_layer; + + if ((i==0) || (this_layer < m_min_layer)) m_min_layer=this_layer; + if ((i==0) || (this_layer > m_max_layer)) m_max_layer=this_layer; } - else if (tag_type == SWF::DEFINEBUTTON2) - { +} + +void +button_character_definition::readDefineButton2(stream* in, movie_definition* m) +{ + // Character ID has been read already + // Read the menu flag // (this is a single bit, the other 7 bits are reserved) m_menu = in->read_u8() != 0; unsigned button_2_action_offset = in->read_u16(); + unsigned long tagEndPosition = in->get_tag_end_position(); unsigned next_action_pos = in->get_position() + button_2_action_offset - 2; + if ( next_action_pos > tagEndPosition ) + { + IF_VERBOSE_MALFORMED_SWF( + log_swferror(_("Next Button2 actionOffset (%u) points past the end of tag (%lu)"), + button_2_action_offset, tagEndPosition); + ); + return; + } + + unsigned long endOfButtonRecords = tagEndPosition; + if ( ! button_2_action_offset ) endOfButtonRecords = tagEndPosition; + // Read button records. - for (;;) + // takes at least 1 byte for the end mark button record, so + // we don't attempt to parse at all unless we have at least 1 byte left + while ( in->get_position() < endOfButtonRecords ) { button_record r; - if (r.read(in, tag_type, m) == false) + if (r.read(in, SWF::DEFINEBUTTON2, m, endOfButtonRecords) == false) { // Null record; marks the end of button records. break; @@ -295,24 +326,17 @@ } } - if ( next_action_pos >= in->get_tag_end_position() ) - { - IF_VERBOSE_MALFORMED_SWF( - log_swferror(_("Next Button2 actionOffset (%u) points past the end of tag"), button_2_action_offset); - ); - return; - } - in->set_position(next_action_pos); // Read Button2ActionConditions - for (;;) + // Don't read past tag end + while ( in->get_position() < tagEndPosition ) { unsigned next_action_offset = in->read_u16(); next_action_pos = in->get_position() + next_action_offset - 2; m_button_actions.resize(m_button_actions.size() + 1); - m_button_actions.back().read(in, tag_type); + m_button_actions.back().read(in, SWF::DEFINEBUTTON2); if (next_action_offset == 0 ) { @@ -333,8 +357,6 @@ // seek to next action. in->set_position(next_action_pos); } - } - // detect min/max layer number m_min_layer=0; @@ -348,6 +370,69 @@ } } +void +button_character_definition::readDefineButtonSound(stream* in, movie_definition* m) +{ + // Character ID has been read already + + if ( m_sound ) + { + IF_VERBOSE_MALFORMED_SWF( + log_swferror(_("Attempt to redefine button sound ignored")); + ); + return; + } + + m_sound = new button_sound_def(); + + IF_VERBOSE_PARSE( + log_parse(_("button sound options: ")); + ); + + for (int i = 0; i < 4; i++) + { + button_sound_info& bs = m_sound->m_button_sounds[i]; + bs.m_sound_id = in->read_u16(); + if (bs.m_sound_id) + { + bs.m_sam = m->get_sound_sample(bs.m_sound_id); + if ( ! bs.m_sam ) + { + IF_VERBOSE_MALFORMED_SWF( + log_swferror(_("sound tag not found, sound_id=%d, button state #=%i"), bs.m_sound_id, i); + ); + } + IF_VERBOSE_PARSE( + log_parse("\n sound_id = %d", bs.m_sound_id); + ); + bs.m_sound_style.read(in); + } + } +} + + +void +button_character_definition::read(stream* in, int tag_type, movie_definition* m) +// Initialize from the given stream. +{ + // Character ID has been read already + + switch (tag_type) + { + case SWF::DEFINEBUTTON: + readDefineButton(in, m); + break; + case SWF::DEFINEBUTTONSOUND: + readDefineButtonSound(in, m); + break; + case SWF::DEFINEBUTTON2: + readDefineButton2(in, m); + break; + default: + abort(); + } +} + character* button_character_definition::create_character_instance( Index: server/parser/button_character_def.h =================================================================== RCS file: /sources/gnash/gnash/server/parser/button_character_def.h,v retrieving revision 1.20 retrieving revision 1.21 diff -u -b -r1.20 -r1.21 --- server/parser/button_character_def.h 4 Dec 2007 11:45:32 -0000 1.20 +++ server/parser/button_character_def.h 12 Dec 2007 23:49:28 -0000 1.21 @@ -56,7 +56,11 @@ /// Read a button record from the SWF stream. // /// Return true if we read a record; false if this is a null - bool read(stream* in, int tag_type, movie_definition* m); + /// + /// @param endPos + /// Last stream offset available for a valid read + /// + bool read(stream* in, int tag_type, movie_definition* m, unsigned long endPos); /// Return true if the button_record is valid // @@ -96,6 +100,8 @@ int m_conditions; typedef std::vector<action_buffer*> ActionList; + + // TODO: define ownership of list elements !! ActionList m_actions; ~button_action(); @@ -153,7 +159,9 @@ struct button_sound_def { - void read(stream* in, movie_definition* m); + // TODO: implement ? + //void read(stream* in, movie_definition* m); + button_sound_info m_button_sounds[4]; #ifdef GNASH_USE_GC @@ -181,6 +189,7 @@ typedef std::vector<button_action> ButtonActVect; ButtonActVect m_button_actions; + // TODO: define ownership of this sound ! button_sound_def* m_sound; button_character_definition(); @@ -189,8 +198,18 @@ /// Create a mutable instance of our definition. character* create_character_instance(character* parent, int id); + /// Read a SWF::DEFINEBUTTON, SWF::DEFINEBUTTONSOUND or SWF::DEFINEBUTTON2 void read(stream* in, int tag_type, movie_definition* m); + /// Read a SWF::DEFINEBUTTON tag + void readDefineButton(stream* in, movie_definition* m); + + /// Read a SWF::DEFINEBUTTON2 tag + void readDefineButton2(stream* in, movie_definition* m); + + /// Read a SWF::DEFINEBUTTONSOUND tag + void readDefineButtonSound(stream* in, movie_definition* m); + const rect& get_bound() const { // It is required that get_bound() is implemented in character definition // classes. However, button character definitions do not have shape _______________________________________________ Gnash-commit mailing list Gnash-commit@gnu.org http://lists.gnu.org/mailman/listinfo/gnash-commit