gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-commit] gnash ChangeLog server/swf/ASHandlers.cpp serve...


From: Sandro Santilli
Subject: [Gnash-commit] gnash ChangeLog server/swf/ASHandlers.cpp serve...
Date: Fri, 30 Jun 2006 20:07:44 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Changes by:     Sandro Santilli <strk>  06/06/30 20:07:44

Modified files:
        .              : ChangeLog 
        server/swf     : ASHandlers.cpp ASHandlers.h 

Log message:
                * server/swf/ASHandlers.cpp, server/swf/ASHandlers.h:
                added ensure_stack() function to use by action handlers
                to check stack size before attempting to fetch from it.
                This cleanly handles malformed SWF and prints an error about
                it.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.449&r2=1.450
http://cvs.savannah.gnu.org/viewcvs/gnash/server/swf/ASHandlers.cpp?cvsroot=gnash&r1=1.23&r2=1.24
http://cvs.savannah.gnu.org/viewcvs/gnash/server/swf/ASHandlers.h?cvsroot=gnash&r1=1.3&r2=1.4

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.449
retrieving revision 1.450
diff -u -b -r1.449 -r1.450
--- ChangeLog   30 Jun 2006 16:07:50 -0000      1.449
+++ ChangeLog   30 Jun 2006 20:07:43 -0000      1.450
@@ -1,3 +1,11 @@
+2006-06-30 Sandro Santilli <address@hidden>
+
+       * server/swf/ASHandlers.cpp, server/swf/ASHandlers.h:
+       added ensure_stack() function to use by action handlers
+       to check stack size before attempting to fetch from it.
+       This cleanly handles malformed SWF and prints an error about
+       it.
+
 2006-06-30 Vitaly Alexeev <address@hidden>
 
        * server\sprite_instance.cpp:  fixed elvis.swf bug

Index: server/swf/ASHandlers.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/swf/ASHandlers.cpp,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -b -r1.23 -r1.24
--- server/swf/ASHandlers.cpp   30 Jun 2006 14:52:25 -0000      1.23
+++ server/swf/ASHandlers.cpp   30 Jun 2006 20:07:44 -0000      1.24
@@ -608,17 +608,21 @@
 
        as_environment& env = thread.env;
 
+       ensure_stack(env, 1);
+
        // If we haven't loaded a specified frame yet, then we're supposed
        // to skip some specified number of actions.
        //
        // Since we don't load incrementally, just ignore this opcode.
 
+#if 0 // replaced by ensure_stack() above
        if ( env.stack_size() < 1 )
        {
                log_error("Empty stack on ActionWaitForFrame. Bogus SWF?");
                // yeah.. as if gnash was bugfree :)
                return;
        }
+#endif // 0
 
        env.drop(1);
 
@@ -680,6 +684,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 2);
     env.top(1) += env.top(0);
     env.drop(1);
 }
@@ -689,6 +694,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 2);
     env.top(1) -= env.top(0);
     env.drop(1);
 }
@@ -698,6 +704,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 2);
     env.top(1) *= env.top(0);
     env.drop(1);
 }
@@ -707,6 +714,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 2);
     env.top(1) /= env.top(0);
     env.drop(1);
 }
@@ -716,6 +724,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 2);
     env.top(1).set_bool(env.top(1) == env.top(0));
     env.drop(1);
 }
@@ -725,6 +734,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 2);
     env.top(1).set_bool(env.top(1) < env.top(0));
     env.drop(1);
 }
@@ -734,6 +744,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 2);
     env.top(1).set_bool(env.top(1).to_bool() && env.top(0).to_bool());
     env.drop(1);
 }
@@ -743,6 +754,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 2);
     env.top(1).set_bool(env.top(1).to_bool() || env.top(0).to_bool());
     env.drop(1);
 }
@@ -752,6 +764,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 1);
     env.top(0).set_bool(! env.top(0).to_bool());
 }
 
@@ -760,6 +773,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 2);
     env.top(1).set_bool(env.top(1).to_tu_string() == 
env.top(0).to_tu_string());
     env.drop(1);    
 }
@@ -769,6 +783,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 1);
     int version = env.get_target()->get_movie_definition()->get_version();    
     
env.top(0).set_int(env.top(0).to_tu_string_versioned(version).utf8_length());
 }
@@ -778,6 +793,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 3); // size, base, string
     int        size = int(env.top(0).to_number());
     int        base = int(env.top(1).to_number()) - 1;  // 1-based indices
     int version = env.get_target()->get_movie_definition()->get_version();    
@@ -803,15 +819,9 @@
 {
 //    GNASH_REPORT_FUNCTION;
        as_environment& env = thread.env;
-       if ( ! env.stack_size() )
-       {
-               // Malformed SWF
-               log_warning("Empty stack on ActionPop, bogus SWF ?");
-       }
-       else
-       {
+       // this is an overhead only if SWF is malformed.
+       ensure_stack(env, 1);
                env.drop(1);
-       }
 }
 
 void
@@ -819,6 +829,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 1);
     env.top(0).set_int(int(floor(env.top(0).to_number())));
 }
 
@@ -827,6 +838,8 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 1); // variable name
+
     as_value var_name = env.pop();
     tu_string var_string = var_name.to_tu_string();
     
@@ -852,7 +865,7 @@
        as_environment& env = thread.env;
 
        // stack must be contain at least two items
-       assert ( env.stack_size() > 1 );
+       ensure_stack(env, 2); 
 
        env.set_variable(env.top(1).to_tu_string(), env.top(0));
        log_action("\n-- set var: %s", env.top(1).to_string());
@@ -867,10 +880,14 @@
 
        as_environment& env = thread.env;
 
+       ensure_stack(env, 1);  // target name
+
        //Vitaly: env.drop(1) remove object on which refers const char * 
target_name
+       //strk: shouldn't we use env.pop() instead ?
        //const char * target_name = env.top(0).to_string();
        tu_string target_name = env.top(0).to_string();
        env.drop(1); // pop the target name off the stack
+
        sprite_instance *new_target;
     
        // if the string is blank, we set target to the root movie
@@ -902,6 +919,9 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+
+    ensure_stack(env, 2); // two strings
+
     int version = env.get_target()->get_movie_definition()->get_version();    
     env.top(1).convert_to_string_versioned(version);
     env.top(1).string_concat(env.top(0).to_tu_string_versioned(version));
@@ -913,6 +933,9 @@
 {
 //    GNASH_REPORT_FUNCTION;
        as_environment& env = thread.env;
+
+    ensure_stack(env, 2); // prop num, target
+
        sprite_instance *target = env.find_target(env.top(1));
        unsigned int prop_number = (unsigned int)env.top(0).to_number();
        if (target)
@@ -928,6 +951,7 @@
                {
                        log_error("invalid property query, property "
                                "number %d\n", prop_number);
+                   env.top(1) = as_value();
                }
        }
        else
@@ -943,6 +967,8 @@
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
     
+    ensure_stack(env, 3); // prop val, prop num, target
+
     sprite_instance *target = env.find_target(env.top(2));
     unsigned int prop_number = (unsigned int)env.top(1).to_number();
     as_value prop_val = env.top(0);
@@ -967,6 +993,9 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+
+    ensure_stack(env, 3); 
+
     env.get_target()->clone_display_object(
         env.top(2).to_tu_string(),
         env.top(1).to_tu_string(),
@@ -980,6 +1009,9 @@
 //     GNASH_REPORT_FUNCTION;
        as_environment& env = thread.env;
 
+    ensure_stack(env, 1); 
+
+    // strk: why not using pop() ?
        env.get_target()->remove_display_object(env.top(0).to_tu_string());
        env.drop(1);
 }
@@ -990,6 +1022,10 @@
 {
 ////    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+
+    ensure_stack(env, 1); 
+
+    // strk: why not using pop() ?
     dbglogfile << env.top(0).to_string() << endl;
     env.drop(1);
 }
@@ -999,6 +1035,9 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+
+    ensure_stack(env, 3); 
+
     movie::drag_state  st;
     
     st.m_character = env.find_target(env.top(0));
@@ -1010,6 +1049,12 @@
     st.m_lock_center = env.top(1).to_bool();
     st.m_bound = env.top(2).to_bool();
     if (st.m_bound) {
+
+        // strk: this works if we didn't drop any before, in 
+        // a contrary case (if we used pop(), which I suggest)
+        // we must remember to updated this as required
+        ensure_stack(env, 7);
+
         st.m_bound_x0 = (float) env.top(6).to_number();
         st.m_bound_y0 = (float) env.top(5).to_number();
         st.m_bound_x1 = (float) env.top(4).to_number();
@@ -1042,6 +1087,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 2); 
     env.top(1).set_bool(env.top(1).to_tu_string() < env.top(0).to_tu_string());
 }
 
@@ -1053,6 +1099,8 @@
     dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
 }
 
+// TODO: continue adding ensure_stack() calls (above done)
+
 void
 SWFHandlers::ActionCastOp(ActionExec& thread)
 {
@@ -1060,6 +1108,8 @@
 
        as_environment& env = thread.env;
 
+       ensure_stack(env, 2);  // super, instance
+
        // Get the "super" function
        function_as_object* super = env.top(0).to_as_function();
 
@@ -1103,6 +1153,9 @@
 {
 //     GNASH_REPORT_FUNCTION;
        as_environment& env = thread.env;
+
+       ensure_stack(env, 1);  // max
+
        int     max = int(env.top(0).to_number());
        if (max < 1) max = 1;
        env.top(0).set_int(tu_random::next_random() % max);
@@ -1121,6 +1174,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 1);  
     env.top(0).set_int(env.top(0).to_string()[0]);
 }
 
@@ -1129,6 +1183,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 1);  
     char       buf[2];
     buf[0] = int(env.top(0).to_number());
     buf[1] = 0;
@@ -1304,6 +1359,9 @@
 {
 //     GNASH_REPORT_FUNCTION;
        as_environment& env = thread.env;
+
+       ensure_stack(env, 2); // target, url
+
        const action_buffer& code = thread.code;
 
        assert( code[thread.pc] == SWF::ACTION_GETURL2 );
@@ -1349,6 +1407,9 @@
 //     GNASH_REPORT_FUNCTION;
 
        as_environment& env = thread.env;
+
+       ensure_stack(env, 1); // bool
+
        const action_buffer& code = thread.code;
 
        // Alias these
@@ -1381,6 +1442,8 @@
 //     GNASH_REPORT_FUNCTION;
        as_environment& env = thread.env;
 
+       ensure_stack(env, 1); // frame spec
+
        // Note: no extra data in this instruction!
        assert(env.get_target());
        env.get_target()->call_frame_actions(env.top(0));
@@ -1393,6 +1456,9 @@
 //     GNASH_REPORT_FUNCTION;
 
        as_environment& env = thread.env;
+
+       ensure_stack(env, 1); // expression
+
        const action_buffer& code = thread.code;
        size_t pc = thread.pc;
 
@@ -1471,6 +1537,8 @@
 //     GNASH_REPORT_FUNCTION;
        as_environment& env = thread.env;
 
+       ensure_stack(env, 2); // var, object
+
        as_value var = env.pop();
        as_value object = env.top(0);
        if (object.get_type() == as_value::OBJECT)
@@ -1496,6 +1564,9 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+
+    ensure_stack(env, 2); // var
+
     as_value var = env.top(0);
     
     as_value oldval = env.get_variable_raw(var.to_tu_string()); 
@@ -1516,6 +1587,8 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 2); // value, var
+
     as_value value = env.pop();
     as_value varname = env.pop();
     env.set_local(varname.to_tu_string(), value);
@@ -1527,6 +1600,8 @@
        //GNASH_REPORT_FUNCTION;
        as_environment& env = thread.env;
 
+       ensure_stack(env, 2); // func name, nargs
+
        //cerr << "At ActionCallFunction enter:"<<endl;
        //env.dump_stack();
 
@@ -1555,6 +1630,8 @@
        }
        int     nargs = (int)env.top(1).to_number();
 
+       ensure_stack(env, 2+nargs); // func name, nargs, args
+
        //log_msg("Function's nargs: %d", nargs);
     
        as_value result = call_method(function, &env, env.get_target(),
@@ -1579,6 +1656,8 @@
        //log_msg("Before top/drop (retval=%p)", (void*)retval);
        //env.dump_stack();
 
+       ensure_stack(env, 1); // ret value
+
        // Put top of stack in the provided return slot, if
        // it's not NULL.
        if (retval) {
@@ -1599,6 +1678,9 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+
+    ensure_stack(env, 2); // x, ,y
+
     as_value   result;
     double     y = env.pop().to_number();
     double     x = env.pop().to_number();
@@ -1616,6 +1698,9 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+
+    ensure_stack(env, 2); // classname, nargs
+
 //    doActionNew(env, with_stack);
 
     as_value   classname = env.pop();
@@ -1623,6 +1708,8 @@
                classname.to_tu_string().c_str());
     int        nargs = (int) env.pop().to_number();
 
+    ensure_stack(env, nargs); // previous 2 entries popped
+
     as_value constructor = env.get_variable(classname.to_tu_string());
     as_value new_obj;
     if (constructor.get_type() == as_value::C_FUNCTION)        {
@@ -1677,6 +1764,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 1); // var name
     const tu_string &varname = env.top(0).to_tu_string();
     env.declare_local(varname);
     env.drop(1);
@@ -1687,7 +1775,13 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+
+    ensure_stack(env, 1); // array size name
+
     int        array_size = (int) env.pop().to_number();
+    assert(array_size >= 0);
+
+    ensure_stack(env, (unsigned int)array_size); // array elements
     
     //log_msg("xxx init array: size = %d, top of stack = %d\n", array_size, 
env.get_top_index());//xxxxx
     
@@ -1719,6 +1813,9 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+
+    ensure_stack(env, 1); // nmembers
+
     // 
     //    SWFACTION_PUSH
     //     [000]   Constant: 1 "obj"
@@ -1729,6 +1826,8 @@
     
     int nmembers = (int) env.pop().to_number();
     
+    ensure_stack(env, nmembers); // members
+    
     smart_ptr<as_object> new_obj_ptr(new as_object); 
     
     // Set provided members
@@ -1754,6 +1853,9 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+
+    ensure_stack(env, 1); 
+
     switch(env.top(0).get_type()) {
       case as_value::UNDEFINED:
           env.top(0).set_string("undefined");
@@ -1778,6 +1880,7 @@
           break;
       default:
           log_error("typeof unknown type: %02X\n", env.top(0).get_type());
+          env.top(0).set_undefined();
           break;
     }
 }
@@ -1795,6 +1898,9 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+
+    ensure_stack(env, 1);  // var_name
+
     as_value var_name = env.pop();
     const tu_string& var_string = var_name.to_tu_string();
     
@@ -1851,6 +1957,9 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+
+    ensure_stack(env, 2); 
+
     int version = env.get_target()->get_movie_definition()->get_version();    
     if (env.top(0).get_type() == as_value::STRING
         || env.top(1).get_type() == as_value::STRING) {
@@ -1867,6 +1976,9 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+
+    ensure_stack(env, 2); 
+
     if (env.top(1).get_type() == as_value::STRING) {
         env.top(1).set_bool(env.top(1).to_tu_string() < 
env.top(0).to_tu_string());
     } else {
@@ -1880,6 +1992,9 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+
+    ensure_stack(env, 2); 
+
     env.top(1).set_bool(env.top(1) == env.top(0));
     env.drop(1);
 }
@@ -1889,6 +2004,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 1); 
     env.top(0).convert_to_number();
 }
 
@@ -1897,6 +2013,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 1); 
     int version = env.get_target()->get_movie_definition()->get_version();    
     env.top(0).convert_to_string_versioned(version);
 }
@@ -1906,6 +2023,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 1); 
     env.push(env.top(0));
 }
 
@@ -1914,6 +2032,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 2); 
     as_value   temp = env.top(1);
     env.top(1) = env.top(0);
     env.top(0) = temp;
@@ -1925,6 +2044,8 @@
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
 
+    ensure_stack(env, 2); // member name, target
+
     // Some corner case behaviors depend on the SWF file version.
     int version = env.get_target()->get_movie_definition()->get_version();
     
@@ -1967,6 +2088,9 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+
+    ensure_stack(env, 3); // value, member, object
+
     as_object* obj = env.top(2).to_object();
     if (obj) {
         obj->set_member(env.top(1).to_tu_string(), env.top(0));
@@ -1989,6 +2113,9 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+
+    ensure_stack(env, 1); 
+
     env.top(0) += 1;
 }
 
@@ -1997,6 +2124,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 1); 
     env.top(0) -= 1;
 }
 
@@ -2006,6 +2134,8 @@
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
 
+    ensure_stack(env, 3);  // method_name, obj, nargs
+
     as_value result;
 
     // Some corner case behaviors depend on the SWF file version.
@@ -2024,6 +2154,9 @@
     int        nargs = (int) env.top(2).to_number();
     log_action(" method nargs: %d\n", nargs);
 
+    ensure_stack(env, 3+nargs); // actual args
+
+
     if (!obj) {
         log_error("call_method invoked in something that "
                   "doesn't cast to an as_object: %s\n",
@@ -2068,6 +2201,8 @@
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
 
+    ensure_stack(env, 2); // super, instance
+
     // Get the "super" function
     function_as_object* super = env.top(0).to_as_function();
 
@@ -2104,6 +2239,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 2); 
     env.top(1) &= env.top(0);
     env.drop(1);
 }
@@ -2113,6 +2249,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 2); 
     env.top(1) |= env.top(0);
     env.drop(1);
 }
@@ -2122,6 +2259,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 2); 
     env.top(1) ^= env.top(0);
     env.drop(1);
 }
@@ -2131,6 +2269,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 2); 
     env.top(1).asr(env.top(0));
     env.drop(1);
 }
@@ -2140,6 +2279,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 2); 
     env.top(1).lsr(env.top(0));
     env.drop(1);
 }
@@ -2149,6 +2289,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 2); 
     env.top(1).lsr(env.top(0));
     env.drop(1);
 }
@@ -2158,6 +2299,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 2); 
     if (env.top(1).get_type() != env.top(0).get_type()) {
         // Types don't match.
         env.top(1).set_bool(false);
@@ -2173,6 +2315,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 2); 
     if (env.top(1).get_type() == as_value::STRING) {
         env.top(1).set_bool(env.top(1).to_tu_string() > 
env.top(0).to_tu_string());
     } else {
@@ -2186,6 +2329,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     as_environment& env = thread.env;
+    ensure_stack(env, 2); 
     env.top(1).set_bool(env.top(1).to_tu_string() > env.top(0).to_tu_string());
     env.drop(1);
 }
@@ -2298,6 +2442,9 @@
     dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
 
        as_environment& env = thread.env;
+
+       ensure_stack(env, 1); 
+
        const action_buffer& code = thread.code;
        std::vector<with_stack_entry>& with_stack = thread.with_stack;
 
@@ -2402,6 +2549,9 @@
 //     GNASH_REPORT_FUNCTION;
 
        as_environment& env = thread.env;
+
+       ensure_stack(env, 1); 
+
        const action_buffer& code = thread.code;
 
        int reg = code[thread.pc + 3];
@@ -2445,6 +2595,23 @@
        }
 }
 
+/*static private*/
+void
+SWFHandlers::fix_stack_underrun(as_environment& env, size_t required)
+{
+    assert ( env.stack_size() < required );
+
+    log_error("Stack underrun: %d elements required, %d available. "
+        "Fixing by pushing undefined values on the missing slots.",
+        required, env.stack_size());
+
+    size_t missing = required-env.stack_size();
+    for (size_t i=0; i<required; ++i)
+    {
+        env.push(as_value());
+    }
+}
+
 } // namespace gnash::SWF
 
 } // namespace gnash

Index: server/swf/ASHandlers.h
===================================================================
RCS file: /sources/gnash/gnash/server/swf/ASHandlers.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- server/swf/ASHandlers.h     30 Jun 2006 00:15:45 -0000      1.3
+++ server/swf/ASHandlers.h     30 Jun 2006 20:07:44 -0000      1.4
@@ -42,6 +42,7 @@
 #include <map>
 #include <vector>
 #include "action.h" // we should get rid of this probably
+#include "as_environment.h" // for ensure_stack inline (must be inlined!)
 #include "swf.h"
 #include "log.h"
 
@@ -69,6 +70,8 @@
     ARG_FUNCTION2
 } as_arg_t;
 
+// @@strk@@ should we move this to .cpp file ? it's only
+// use is within SWFHandlers, anyway...
 typedef void (*action_callback_t)(ActionExec& thread);
 //as_environment &env, action_buffer& code, size_t& PC);
 class ActionHandler
@@ -140,6 +143,23 @@
 
 private:
 
+       // Ensure the stack has at least 'required' elements, fixing
+       // it if required.
+       // This is an inline to it can eventually be made a no-op
+       // when gnash works and input SWFs are known to be valid.
+       static void ensure_stack(as_environment& env, size_t required)
+       {
+               if ( env.stack_size() < required )
+               {
+                       fix_stack_underrun(env, required);
+               }
+       }
+
+       // Fill all the slots to reach the 'required' stack size
+       // with undefined values. This method should *only* be
+       // called by ensure_stack() above.
+       static void fix_stack_underrun(as_environment& env, size_t required);
+
        static void ActionEnd(ActionExec& thread);
        static void ActionNextFrame(ActionExec& thread);
        static void ActionPrevFrame(ActionExec& thread);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]