[Swfdec] 8 commits - doc/swfdec-sections.txt libswfdec/swfdec_as_context.c libswfdec/swfdec_as_context.h libswfdec/swfdec_as_interpret.c test/trace

Pekka Lampila medar at kemper.freedesktop.org
Fri Oct 26 16:36:19 PDT 2007


 doc/swfdec-sections.txt                     |    2 
 libswfdec/swfdec_as_context.c               |   54 ++++++++++++++++++-
 libswfdec/swfdec_as_context.h               |    9 ++-
 libswfdec/swfdec_as_interpret.c             |   79 ++++++++++++++--------------
 test/trace/Makefile.am                      |    7 ++
 test/trace/try-throw-in-finally-6.swf       |binary
 test/trace/try-throw-in-finally-6.swf.trace |    2 
 test/trace/try-throw-in-finally-7.swf       |binary
 test/trace/try-throw-in-finally-7.swf.trace |    2 
 test/trace/try-throw-in-finally-8.swf       |binary
 test/trace/try-throw-in-finally-8.swf.trace |    2 
 test/trace/try-throw-in-finally.as          |   17 ++++++
 12 files changed, 130 insertions(+), 44 deletions(-)

New commits:
commit fae96ec372e251304845515d222ee784574d1a7b
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Sat Oct 27 02:19:19 2007 +0300

    Add a test to see what exception gets thrown out of Try action's finally block

diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index 78767a2..2ff2699 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -2054,6 +2054,13 @@ EXTRA_DIST = \
 	transform2.swf \
 	transform2.swf.trace \
 	transform2.swf.trace.org \
+	try-throw-in-finally.as \
+	try-throw-in-finally-6.swf \
+	try-throw-in-finally-6.swf.trace \
+	try-throw-in-finally-7.swf \
+	try-throw-in-finally-7.swf.trace \
+	try-throw-in-finally-8.swf \
+	try-throw-in-finally-8.swf.trace \
 	undefined-tostring.swf \
 	undefined-tostring.swf.trace \
 	undefined1.swf \
diff --git a/test/trace/try-throw-in-finally-5.swf b/test/trace/try-throw-in-finally-5.swf
new file mode 100644
index 0000000..e69de29
diff --git a/test/trace/try-throw-in-finally-6.swf b/test/trace/try-throw-in-finally-6.swf
new file mode 100644
index 0000000..99fb7d4
Binary files /dev/null and b/test/trace/try-throw-in-finally-6.swf differ
diff --git a/test/trace/try-throw-in-finally-6.swf.trace b/test/trace/try-throw-in-finally-6.swf.trace
new file mode 100644
index 0000000..d8d2aa6
--- /dev/null
+++ b/test/trace/try-throw-in-finally-6.swf.trace
@@ -0,0 +1,2 @@
+Test what exception is thrown out of finally
+finally
diff --git a/test/trace/try-throw-in-finally-7.swf b/test/trace/try-throw-in-finally-7.swf
new file mode 100644
index 0000000..85ba3ef
Binary files /dev/null and b/test/trace/try-throw-in-finally-7.swf differ
diff --git a/test/trace/try-throw-in-finally-7.swf.trace b/test/trace/try-throw-in-finally-7.swf.trace
new file mode 100644
index 0000000..d8d2aa6
--- /dev/null
+++ b/test/trace/try-throw-in-finally-7.swf.trace
@@ -0,0 +1,2 @@
+Test what exception is thrown out of finally
+finally
diff --git a/test/trace/try-throw-in-finally-8.swf b/test/trace/try-throw-in-finally-8.swf
new file mode 100644
index 0000000..7390efb
Binary files /dev/null and b/test/trace/try-throw-in-finally-8.swf differ
diff --git a/test/trace/try-throw-in-finally-8.swf.trace b/test/trace/try-throw-in-finally-8.swf.trace
new file mode 100644
index 0000000..d8d2aa6
--- /dev/null
+++ b/test/trace/try-throw-in-finally-8.swf.trace
@@ -0,0 +1,2 @@
+Test what exception is thrown out of finally
+finally
diff --git a/test/trace/try-throw-in-finally.as b/test/trace/try-throw-in-finally.as
new file mode 100644
index 0000000..b80ef4e
--- /dev/null
+++ b/test/trace/try-throw-in-finally.as
@@ -0,0 +1,17 @@
+// makeswf -v 7 -r 1 -o try-throw-in-finally-7.swf try-throw-in-finally.as
+
+trace ("Test what exception is thrown out of finally");
+
+try {
+  try {
+    throw "try";
+  } catch (exception) {
+    throw "catch";
+  } finally {
+    throw "finally";
+  };
+} catch (exception) {
+  trace (exception);
+};
+
+loadMovie ("FSCommand:quit", "");
commit 65fb16c53625ead227c6dfafd0d9da75a43b95a8
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Sat Oct 27 02:13:01 2007 +0300

    Rename context->throwing to exception and throw_value to exception_value

diff --git a/libswfdec/swfdec_as_context.c b/libswfdec/swfdec_as_context.c
index 403e03d..663a15c 100644
--- a/libswfdec/swfdec_as_context.c
+++ b/libswfdec/swfdec_as_context.c
@@ -361,7 +361,7 @@ static void
 swfdec_as_context_do_mark (SwfdecAsContext *context)
 {
   swfdec_as_object_mark (context->global);
-  swfdec_as_value_mark (&context->throw_value);
+  swfdec_as_value_mark (&context->exception_value);
   swfdec_as_object_mark (context->Function);
   swfdec_as_object_mark (context->Function_prototype);
   swfdec_as_object_mark (context->Object);
@@ -685,10 +685,10 @@ swfdec_as_context_throw (SwfdecAsContext *context, const SwfdecAsValue *value)
 {
   g_return_if_fail (SWFDEC_IS_AS_CONTEXT (context));
   g_return_if_fail (SWFDEC_IS_AS_VALUE (value));
-  g_return_if_fail (!context->throwing);
+  g_return_if_fail (!context->exception);
 
-  context->throwing = TRUE;
-  context->throw_value = *value;
+  context->exception = TRUE;
+  context->exception_value = *value;
 }
 
 /**
@@ -706,14 +706,14 @@ swfdec_as_context_catch (SwfdecAsContext *context, SwfdecAsValue *value)
 {
   g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), FALSE);
 
-  if (!context->throwing)
+  if (!context->exception)
     return FALSE;
 
   if (value != NULL)
-    *value = context->throw_value;
+    *value = context->exception_value;
 
-  context->throwing = FALSE;
-  SWFDEC_AS_VALUE_SET_UNDEFINED (&context->throw_value);
+  context->exception = FALSE;
+  SWFDEC_AS_VALUE_SET_UNDEFINED (&context->exception_value);
 
   return TRUE;
 }
@@ -858,14 +858,14 @@ start:
   while (context->state < SWFDEC_AS_CONTEXT_ABORTED) {
     // in case of an exception, skip blocks until exception is cleared or we
     // run out of blocks
-    while (context->throwing && frame->blocks->len > 0) {
+    while (context->exception && frame->blocks->len > 0) {
       frame->pc = frame->block_end;
       swfdec_as_frame_check_block (frame);
       pc = frame->pc;
     }
-    if (context->throwing) {
+    if (context->exception) {
       SWFDEC_ERROR ("Unhandled exception: %s",
-	  swfdec_as_value_to_string (context, &context->throw_value));
+	  swfdec_as_value_to_string (context, &context->exception_value));
       goto error;
     }
     if (check_block && (pc < frame->block_start || pc >= frame->block_end)) {
diff --git a/libswfdec/swfdec_as_context.h b/libswfdec/swfdec_as_context.h
index 145f647..df09fa2 100644
--- a/libswfdec/swfdec_as_context.h
+++ b/libswfdec/swfdec_as_context.h
@@ -63,8 +63,8 @@ struct _SwfdecAsContext {
   unsigned int		call_depth;   	/* current depth of call stack (equals length of frame list) */
   SwfdecAsFrame *	frame;		/* topmost stack frame */
   SwfdecAsFrame *	last_frame;   	/* last frame before calling context_run */
-  gboolean		throwing;	/* whether we are throwing an error */
-  SwfdecAsValue		throw_value;	/* the error object being thrown */
+  gboolean		exception;	/* whether we are throwing an exception */
+  SwfdecAsValue		exception_value; /* value of the exception being thrown, can be anything including undefined */
 
   /* stack */
   SwfdecAsValue	*	base;		/* stack base */
diff --git a/libswfdec/swfdec_as_interpret.c b/libswfdec/swfdec_as_interpret.c
index 9155290..3defeca 100644
--- a/libswfdec/swfdec_as_interpret.c
+++ b/libswfdec/swfdec_as_interpret.c
@@ -2583,17 +2583,17 @@ swfdec_action_try_data_unref (gpointer data)
 static void
 swfdec_action_try_end_finally (SwfdecAsFrame *frame, gpointer data)
 {
-  SwfdecAsValue *exception = data;
+  SwfdecAsValue *exception_value = data;
   SwfdecAsContext *cx;
 
   g_return_if_fail (SWFDEC_IS_AS_FRAME (frame));
-  g_return_if_fail (SWFDEC_IS_AS_VALUE (exception));
+  g_return_if_fail (SWFDEC_IS_AS_VALUE (exception_value));
 
   cx = SWFDEC_AS_OBJECT (frame)->context;
 
   // finally has ended and we had exception stored, throw it
-  if (!cx->throwing)
-    swfdec_as_context_throw (cx, exception);
+  if (!cx->exception)
+    swfdec_as_context_throw (cx, exception_value);
 
   swfdec_as_frame_pop_block (frame);
 }
@@ -2603,7 +2603,7 @@ swfdec_action_try_end_catch (SwfdecAsFrame *frame, gpointer data)
 {
   TryData *try_data = data;
   SwfdecAsContext *cx;
-  SwfdecAsValue *exception, val;
+  SwfdecAsValue *exception_value, val;
 
   g_return_if_fail (SWFDEC_IS_AS_FRAME (frame));
   g_return_if_fail (try_data != NULL);
@@ -2619,13 +2619,13 @@ swfdec_action_try_end_catch (SwfdecAsFrame *frame, gpointer data)
     // create new block for finally, passing the exception
     // clear exception from the context
 
-    exception = g_malloc (sizeof (SwfdecAsValue));
-    *exception = val;
+    exception_value = g_malloc (sizeof (SwfdecAsValue));
+    *exception_value = val;
 
     // FIXME: the exception value is not marked while finally block runs
     swfdec_as_frame_push_block (frame, try_data->finally_start,
 	try_data->finally_start + try_data->finally_size,
-	swfdec_action_try_end_finally, exception, g_free);
+	swfdec_action_try_end_finally, exception_value, g_free);
   }
 
   swfdec_action_try_data_unref (try_data);
commit 5c3f06cbeb5ee318b13b99565253b2f5ae7637ae
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Sat Oct 27 02:08:13 2007 +0300

    Make Try and Throw implementations use the new throw and catch functions

diff --git a/libswfdec/swfdec_as_interpret.c b/libswfdec/swfdec_as_interpret.c
index f4ecef7..9155290 100644
--- a/libswfdec/swfdec_as_interpret.c
+++ b/libswfdec/swfdec_as_interpret.c
@@ -2538,8 +2538,7 @@ static void
 swfdec_action_throw (SwfdecAsContext *cx, guint action, const guint8 *data,
     guint len)
 {
-  cx->throwing = TRUE;
-  cx->throw_value = *swfdec_as_stack_pop (cx);
+  swfdec_as_context_throw (cx, swfdec_as_stack_pop (cx));
 }
 
 typedef struct {
@@ -2584,19 +2583,17 @@ swfdec_action_try_data_unref (gpointer data)
 static void
 swfdec_action_try_end_finally (SwfdecAsFrame *frame, gpointer data)
 {
-  SwfdecAsValue *error = data;
+  SwfdecAsValue *exception = data;
   SwfdecAsContext *cx;
 
   g_return_if_fail (SWFDEC_IS_AS_FRAME (frame));
-  g_return_if_fail (SWFDEC_IS_AS_VALUE (error));
+  g_return_if_fail (SWFDEC_IS_AS_VALUE (exception));
 
   cx = SWFDEC_AS_OBJECT (frame)->context;
 
   // finally has ended and we had exception stored, throw it
-  if (!cx->throwing) {
-    cx->throwing = TRUE;
-    cx->throw_value = *error;
-  }
+  if (!cx->throwing)
+    swfdec_as_context_throw (cx, exception);
 
   swfdec_as_frame_pop_block (frame);
 }
@@ -2606,7 +2603,7 @@ swfdec_action_try_end_catch (SwfdecAsFrame *frame, gpointer data)
 {
   TryData *try_data = data;
   SwfdecAsContext *cx;
-  SwfdecAsValue *error;
+  SwfdecAsValue *exception, val;
 
   g_return_if_fail (SWFDEC_IS_AS_FRAME (frame));
   g_return_if_fail (try_data != NULL);
@@ -2616,22 +2613,19 @@ swfdec_action_try_end_catch (SwfdecAsFrame *frame, gpointer data)
   swfdec_action_try_data_ref (try_data);
   swfdec_as_frame_pop_block (frame);
 
-  if (cx->throwing)
+  if (swfdec_as_context_catch (cx, &val))
   {
     // we got an exception while in catch block:
     // create new block for finally, passing the exception
     // clear exception from the context
 
-    error = g_malloc (sizeof (SwfdecAsValue));
-    *error = cx->throw_value;
+    exception = g_malloc (sizeof (SwfdecAsValue));
+    *exception = val;
 
-    // FIXME: the error value is not marked while finally block runs
+    // FIXME: the exception value is not marked while finally block runs
     swfdec_as_frame_push_block (frame, try_data->finally_start,
 	try_data->finally_start + try_data->finally_size,
-	swfdec_action_try_end_finally, error, g_free);
-
-    cx->throwing = FALSE;
-    SWFDEC_AS_VALUE_SET_UNDEFINED (&cx->throw_value);
+	swfdec_action_try_end_finally, exception, g_free);
   }
 
   swfdec_action_try_data_unref (try_data);
@@ -2642,6 +2636,7 @@ swfdec_action_try_end_try (SwfdecAsFrame *frame, gpointer data)
 {
   TryData *try_data = data;
   SwfdecAsContext *cx;
+  SwfdecAsValue val;
 
   g_return_if_fail (SWFDEC_IS_AS_FRAME (frame));
   g_return_if_fail (try_data != NULL);
@@ -2658,16 +2653,16 @@ swfdec_action_try_end_try (SwfdecAsFrame *frame, gpointer data)
   swfdec_action_try_data_ref (try_data);
   swfdec_as_frame_pop_block (frame);
 
-  if (cx->throwing)
+  if (swfdec_as_context_catch (cx, &val))
   {
     // we got an exception while in try block:
-    // set the error variable
+    // set the exception variable
     // add new block for catch
     // clear exception from context
     if (try_data->use_register)
     {
       if (swfdec_action_has_register (cx, try_data->register_number)) {
-	cx->frame->registers[try_data->register_number] = cx->throw_value;
+	cx->frame->registers[try_data->register_number] = val;
       } else {
 	SWFDEC_ERROR ("cannot set Error to register %u: not enough registers",
 	    try_data->register_number);
@@ -2683,14 +2678,14 @@ swfdec_action_try_end_try (SwfdecAsFrame *frame, gpointer data)
       if (swfdec_action_get_movie_by_path (cx, s, &object, &rest)) {
 	if (object && rest) {
 	  swfdec_as_object_set_variable (object,
-	      swfdec_as_context_get_string (cx, rest), &cx->throw_value);
+	      swfdec_as_context_get_string (cx, rest), &val);
 	} else {
 	  if (object) {
 	    rest = s;
 	  } else {
 	    rest = swfdec_as_context_get_string (cx, rest);
 	  }
-	  swfdec_as_frame_set_variable (frame, rest, &cx->throw_value);
+	  swfdec_as_frame_set_variable (frame, rest, &val);
 	}
       }
       else
@@ -2704,9 +2699,6 @@ swfdec_action_try_end_try (SwfdecAsFrame *frame, gpointer data)
     swfdec_as_frame_push_block (frame, try_data->catch_start,
 	try_data->catch_start + try_data->catch_size,
 	swfdec_action_try_end_catch, try_data, swfdec_action_try_data_unref);
-
-    cx->throwing = FALSE;
-    SWFDEC_AS_VALUE_SET_UNDEFINED (&cx->throw_value);
   }
 
   swfdec_action_try_data_unref (try_data);
commit 3c105cb641d7c45ff98fd33bfc94f7162010d769
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Sat Oct 27 02:07:48 2007 +0300

    Fix reversed assert in swfdec_as_context_throw

diff --git a/libswfdec/swfdec_as_context.c b/libswfdec/swfdec_as_context.c
index ed491b1..403e03d 100644
--- a/libswfdec/swfdec_as_context.c
+++ b/libswfdec/swfdec_as_context.c
@@ -685,7 +685,7 @@ swfdec_as_context_throw (SwfdecAsContext *context, const SwfdecAsValue *value)
 {
   g_return_if_fail (SWFDEC_IS_AS_CONTEXT (context));
   g_return_if_fail (SWFDEC_IS_AS_VALUE (value));
-  g_return_if_fail (context->throwing);
+  g_return_if_fail (!context->throwing);
 
   context->throwing = TRUE;
   context->throw_value = *value;
commit eae34b29ae9c059478f7f85c9fb519fb67380b2f
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Sat Oct 27 01:57:52 2007 +0300

    Add swfdec_as_context_throw and swfdec_as_context_catch functions

diff --git a/doc/swfdec-sections.txt b/doc/swfdec-sections.txt
index 2442538..2b3a774 100644
--- a/doc/swfdec-sections.txt
+++ b/doc/swfdec-sections.txt
@@ -307,6 +307,8 @@ swfdec_as_context_use_mem
 swfdec_as_context_gc
 swfdec_as_context_maybe_gc
 swfdec_as_context_run
+swfdec_as_context_throw
+swfdec_as_context_catch
 swfdec_as_context_unuse_mem
 swfdec_as_context_eval
 swfdec_as_context_eval_set
diff --git a/libswfdec/swfdec_as_context.c b/libswfdec/swfdec_as_context.c
index 531ff00..ed491b1 100644
--- a/libswfdec/swfdec_as_context.c
+++ b/libswfdec/swfdec_as_context.c
@@ -673,6 +673,52 @@ swfdec_as_context_get_frame (SwfdecAsContext *context)
 }
 
 /**
+ * swfdec_as_context_throw:
+ * @context: a #SwfdecAsContext
+ * @value: a #SwfdecAsValue to be thrown
+ *
+ * Throws a new exception in the @context using the given @value. This function
+ * can only be called if the @context is not already throwing an exception.
+ **/
+void
+swfdec_as_context_throw (SwfdecAsContext *context, const SwfdecAsValue *value)
+{
+  g_return_if_fail (SWFDEC_IS_AS_CONTEXT (context));
+  g_return_if_fail (SWFDEC_IS_AS_VALUE (value));
+  g_return_if_fail (context->throwing);
+
+  context->throwing = TRUE;
+  context->throw_value = *value;
+}
+
+/**
+ * swfdec_as_context_catch:
+ * @context: a #SwfdecAsContext
+ * @value: a #SwfdecAsValue to be thrown
+ *
+ * Removes the currently thrown exception from @context and sets @value to the
+ * thrown value
+ *
+ * Returns: %TRUE if an exception was catched, %FALSE otherwise
+ **/
+gboolean
+swfdec_as_context_catch (SwfdecAsContext *context, SwfdecAsValue *value)
+{
+  g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), FALSE);
+
+  if (!context->throwing)
+    return FALSE;
+
+  if (value != NULL)
+    *value = context->throw_value;
+
+  context->throwing = FALSE;
+  SWFDEC_AS_VALUE_SET_UNDEFINED (&context->throw_value);
+
+  return TRUE;
+}
+
+/**
  * swfdec_as_context_get_time:
  * @context: a #SwfdecAsContext
  * @tv: a #GTimeVal to be set to the context's time
diff --git a/libswfdec/swfdec_as_context.h b/libswfdec/swfdec_as_context.h
index 0f062c8..145f647 100644
--- a/libswfdec/swfdec_as_context.h
+++ b/libswfdec/swfdec_as_context.h
@@ -113,6 +113,11 @@ const char *	swfdec_as_context_give_string	(SwfdecAsContext *	context,
 void		swfdec_as_context_abort		(SwfdecAsContext *	context,
 						 const char *		reason);
 
+void		swfdec_as_context_throw		(SwfdecAsContext *	context,
+						 const SwfdecAsValue *	value);
+gboolean	swfdec_as_context_catch		(SwfdecAsContext *	context,
+						 SwfdecAsValue *	value);
+
 gboolean	swfdec_as_context_use_mem     	(SwfdecAsContext *	context, 
 						 gsize			bytes);
 void		swfdec_as_context_unuse_mem   	(SwfdecAsContext *	context,
commit c9d43105c71931ba583ff12dd0adf5624e50aaa8
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Sat Oct 27 01:19:50 2007 +0300

    Don't abort when we get an unhandled exception

diff --git a/libswfdec/swfdec_as_context.c b/libswfdec/swfdec_as_context.c
index 31a9bdf..531ff00 100644
--- a/libswfdec/swfdec_as_context.c
+++ b/libswfdec/swfdec_as_context.c
@@ -818,7 +818,8 @@ start:
       pc = frame->pc;
     }
     if (context->throwing) {
-      swfdec_as_context_abort (context, "Unhandled exception");
+      SWFDEC_ERROR ("Unhandled exception: %s",
+	  swfdec_as_value_to_string (context, &context->throw_value));
       goto error;
     }
     if (check_block && (pc < frame->block_start || pc >= frame->block_end)) {
commit c4f51df1f6b9ac1b2eea5b22ec43de5a1caa70a8
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Sat Oct 27 01:09:08 2007 +0300

    Mark context->throw_value
    
    Add FIXME comment about not marking throw_value while running finally loop

diff --git a/libswfdec/swfdec_as_context.c b/libswfdec/swfdec_as_context.c
index 6e35622..31a9bdf 100644
--- a/libswfdec/swfdec_as_context.c
+++ b/libswfdec/swfdec_as_context.c
@@ -361,6 +361,7 @@ static void
 swfdec_as_context_do_mark (SwfdecAsContext *context)
 {
   swfdec_as_object_mark (context->global);
+  swfdec_as_value_mark (&context->throw_value);
   swfdec_as_object_mark (context->Function);
   swfdec_as_object_mark (context->Function_prototype);
   swfdec_as_object_mark (context->Object);
diff --git a/libswfdec/swfdec_as_interpret.c b/libswfdec/swfdec_as_interpret.c
index f578829..f4ecef7 100644
--- a/libswfdec/swfdec_as_interpret.c
+++ b/libswfdec/swfdec_as_interpret.c
@@ -2625,6 +2625,7 @@ swfdec_action_try_end_catch (SwfdecAsFrame *frame, gpointer data)
     error = g_malloc (sizeof (SwfdecAsValue));
     *error = cx->throw_value;
 
+    // FIXME: the error value is not marked while finally block runs
     swfdec_as_frame_push_block (frame, try_data->finally_start,
 	try_data->finally_start + try_data->finally_size,
 	swfdec_action_try_end_finally, error, g_free);
commit d5cff3948b57d9b3bc44eb88d652eda10c0d41eb
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Sat Oct 27 00:58:45 2007 +0300

    Clean up Try code. Fix couple of bugs

diff --git a/libswfdec/swfdec_as_interpret.c b/libswfdec/swfdec_as_interpret.c
index cf41ff0..f578829 100644
--- a/libswfdec/swfdec_as_interpret.c
+++ b/libswfdec/swfdec_as_interpret.c
@@ -2544,9 +2544,8 @@ swfdec_action_throw (SwfdecAsContext *cx, guint action, const guint8 *data,
 
 typedef struct {
   int			ref_count;
-  const guint8 *	start;
-  gboolean		catch;
-  gboolean		finally;
+  const guint8 *	catch_start;
+  const guint8 *	finally_start;
   guint			catch_size;
   guint			finally_size;
 
@@ -2626,8 +2625,8 @@ swfdec_action_try_end_catch (SwfdecAsFrame *frame, gpointer data)
     error = g_malloc (sizeof (SwfdecAsValue));
     *error = cx->throw_value;
 
-    swfdec_as_frame_push_block (frame, try_data->start + try_data->catch_size,
-	try_data->start + try_data->catch_size + try_data->finally_size,
+    swfdec_as_frame_push_block (frame, try_data->finally_start,
+	try_data->finally_start + try_data->finally_size,
 	swfdec_action_try_end_finally, error, g_free);
 
     cx->throwing = FALSE;
@@ -2648,7 +2647,7 @@ swfdec_action_try_end_try (SwfdecAsFrame *frame, gpointer data)
 
   // if we don't have a catch block, we handle try block exactly like it was
   // catch block
-  if (!try_data->catch) {
+  if (!try_data->catch_start) {
     swfdec_action_try_end_catch (frame, try_data);
     return;
   }
@@ -2701,9 +2700,9 @@ swfdec_action_try_end_try (SwfdecAsFrame *frame, gpointer data)
     }
 
     swfdec_action_try_data_ref (try_data);
-    swfdec_as_frame_push_block (frame, try_data->start,
-	try_data->start + try_data->catch_size, swfdec_action_try_end_catch,
-	try_data, swfdec_action_try_data_unref);
+    swfdec_as_frame_push_block (frame, try_data->catch_start,
+	try_data->catch_start + try_data->catch_size,
+	swfdec_action_try_end_catch, try_data, swfdec_action_try_data_unref);
 
     cx->throwing = FALSE;
     SWFDEC_AS_VALUE_SET_UNDEFINED (&cx->throw_value);
@@ -2718,6 +2717,7 @@ swfdec_action_try (SwfdecAsContext *cx, guint action, const guint8 *data, guint
   SwfdecBits bits;
   TryData *try_data;
   guint try_size;
+  gboolean use_finally, use_catch;
 
   if (len <= 8) {
     SWFDEC_ERROR ("With action requires a length of at least 8, but got %u",
@@ -2727,18 +2727,22 @@ swfdec_action_try (SwfdecAsContext *cx, guint action, const guint8 *data, guint
   }
 
   try_data = g_malloc0 (sizeof (TryData));
+  swfdec_action_try_data_ref (try_data);
 
   swfdec_bits_init_data (&bits, data, len);
 
   swfdec_bits_getbits (&bits, 5); // reserved
   try_data->use_register = swfdec_bits_getbit (&bits);
-  try_data->finally = swfdec_bits_getbit (&bits);
-  try_data->catch = swfdec_bits_getbit (&bits);
+  use_finally = swfdec_bits_getbit (&bits);
+  use_catch = swfdec_bits_getbit (&bits);
 
   try_size = swfdec_bits_get_u16 (&bits);
   try_data->catch_size = swfdec_bits_get_u16 (&bits);
   try_data->finally_size = swfdec_bits_get_u16 (&bits);
-  try_data->start = data + len + try_size;
+  if (use_catch)
+    try_data->catch_start = data + len + try_size;
+  if (use_finally)
+    try_data->finally_start = try_data->catch_start + try_data->catch_size;
 
   if (try_data->use_register) {
     try_data->register_number = swfdec_bits_get_u8 (&bits);
@@ -2751,9 +2755,13 @@ swfdec_action_try (SwfdecAsContext *cx, guint action, const guint8 *data, guint
     SWFDEC_WARNING ("leftover bytes in Try action");
   }
 
-  swfdec_action_try_data_ref (try_data);
-  swfdec_as_frame_push_block (cx->frame, data + len, data + len + try_size,
-      swfdec_action_try_end_try, try_data, swfdec_action_try_data_unref);
+  if (try_data->catch_start || try_data->finally_start) {
+    swfdec_as_frame_push_block (cx->frame, data + len, data + len + try_size,
+	swfdec_action_try_end_try, try_data, swfdec_action_try_data_unref);
+  } else {
+    SWFDEC_ERROR ("Try without neither catch or finally block");
+    swfdec_action_try_data_unref (try_data);
+  }
 }
 
 static void


More information about the Swfdec mailing list