[Swfdec] Branch 'interpreter' - 4 commits - libswfdec/js libswfdec/swfdec_bits.c libswfdec/swfdec_bits.h libswfdec/swfdec_codec_screen.c libswfdec/swfdec_image.c libswfdec/swfdec_script.c libswfdec/swfdec_swf_decoder.c libswfdec/swfdec_tag.c

Benjamin Otte company at kemper.freedesktop.org
Thu Jan 18 06:06:29 PST 2007


 libswfdec/js/jsinterp.h         |    1 
 libswfdec/swfdec_bits.c         |   28 +++
 libswfdec/swfdec_bits.h         |    9 -
 libswfdec/swfdec_codec_screen.c |    2 
 libswfdec/swfdec_image.c        |   98 ++++--------
 libswfdec/swfdec_script.c       |  315 ++++++++++++++++++++++++++++++++++++++--
 libswfdec/swfdec_swf_decoder.c  |    2 
 libswfdec/swfdec_tag.c          |   23 --
 8 files changed, 371 insertions(+), 107 deletions(-)

New commits:
diff-tree 878ec656b0711cd19c11554d0617109a058af799 (from 8a1b77a18b9266e33c5e92ebeb0a8edbb7b6e643)
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Jan 18 15:05:37 2007 +0100

    implement GetVariable, fix a missing break in print_push and add better debugging

diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index a27f037..49ad92f 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -29,6 +29,7 @@
 
 #include <string.h>
 #include "swfdec_decoder.h"
+#include "swfdec_js.h"
 #include "swfdec_movie.h"
 #include "swfdec_root_movie.h"
 
@@ -305,6 +306,18 @@ swfdec_action_push (JSContext *cx, guint
   return swfdec_bits_left (&bits) ? JS_TRUE : JS_FALSE;
 }
 
+static JSBool
+swfdec_action_get_variable (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+  const char *s;
+
+  s = swfdec_js_to_string (cx, cx->fp->sp[-1]);
+  if (s == NULL)
+    return JS_FALSE;
+  cx->fp->sp[-1] = swfdec_js_eval (cx, cx->fp->scopeChain, s);
+  return JS_TRUE;
+}
+
 /*** PRINT FUNCTIONS ***/
 
 static char *
@@ -352,6 +365,7 @@ swfdec_action_print_push (guint action, 
 	break;
       case 7: /* 32bit int */
 	g_string_append_printf (string, "%u", swfdec_bits_get_u32 (&bits));
+	break;
       case 8: /* 8bit ConstantPool address */
 	g_string_append_printf (string, "Pool %u", swfdec_bits_get_u8 (&bits));
 	break;
@@ -450,7 +464,7 @@ static const SwfdecActionSpec actions[25
   [0x15] = { "StringExtract", NULL },
   [0x17] = { "Pop", NULL },
   [0x18] = { "ToInteger", NULL },
-  [0x1c] = { "GetVariable", NULL },
+  [0x1c] = { "GetVariable", NULL, 1, 1, { NULL, swfdec_action_get_variable, swfdec_action_get_variable, swfdec_action_get_variable, swfdec_action_get_variable } },
   [0x1d] = { "SetVariable", NULL },
   [0x20] = { "SetTarget2", NULL },
   [0x21] = { "StringAdd", NULL },
@@ -604,8 +618,9 @@ validate_action (guint action, const gui
 
   /* ensure there's a function to execute this opcode, otherwise fail */
   if (actions[action].exec[version] == NULL) {
-    SWFDEC_ERROR ("no opcode for %u %s", action, 
-	actions[action].name ? actions[action].name : "Unknown");
+    SWFDEC_ERROR ("no function for %u %s in v%u", action, 
+	actions[action].name ? actions[action].name : "Unknown",
+	script->version);
     return FALSE;
   }
   /* we might want to do stuff here for certain actions */
diff-tree 8a1b77a18b9266e33c5e92ebeb0a8edbb7b6e643 (from c41b8582293535b64bf83c19843bd4eae8662e6f)
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Jan 18 12:52:36 2007 +0100

    implement ConstantPool and Push

diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 5b01510..a27f037 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -27,18 +27,86 @@
 #include "js/jscntxt.h"
 #include "js/jsinterp.h"
 
-/*** SUPPORT FUNCTIONS ***/
-
+#include <string.h>
 #include "swfdec_decoder.h"
 #include "swfdec_movie.h"
 #include "swfdec_root_movie.h"
 
+/*** CONSTANT POOLS ***/
+
+typedef GPtrArray SwfdecConstantPool;
+
+static SwfdecConstantPool *
+swfdec_constant_pool_new_from_action (const guint8 *data, guint len)
+{
+  guint8 *next;
+  guint i, n;
+  GPtrArray *pool;
+
+  if (len < 2) {
+    SWFDEC_ERROR ("constant pool too small");
+    return NULL;
+  }
+  n = GUINT16_FROM_LE (*((guint16*) data));
+  data += 2;
+  len -= 2;
+  pool = g_ptr_array_sized_new (n);
+  g_ptr_array_set_size (pool, n);
+  for (i = 0; i < n; i++) {
+    next = memchr (data, 0, len);
+    if (next == NULL) {
+      SWFDEC_ERROR ("not enough strings available");
+      g_ptr_array_free (pool, TRUE);
+      return NULL;
+    }
+    next++;
+    g_ptr_array_index (pool, i) = (gpointer) data;
+    len -= next - data;
+    data = next;
+  }
+  if (len != 0) {
+    SWFDEC_WARNING ("constant pool didn't consume whole buffer (%u bytes leftover)", len);
+  }
+  return pool;
+}
+
+static guint
+swfdec_constant_pool_size (SwfdecConstantPool *pool)
+{
+  return pool->len;
+}
+
+static const char *
+swfdec_constant_pool_get (SwfdecConstantPool *pool, guint i)
+{
+  g_assert (i < pool->len);
+  return g_ptr_array_index (pool, i);
+}
+
+static void
+swfdec_constant_pool_free (SwfdecConstantPool *pool)
+{
+  g_ptr_array_free (pool, TRUE);
+}
+
+/*** SUPPORT FUNCTIONS ***/
+
 static SwfdecMovie *
 swfdec_action_get_target (JSContext *cx)
 {
   return swfdec_scriptable_from_jsval (cx, OBJECT_TO_JSVAL (cx->fp->scopeChain), SWFDEC_TYPE_MOVIE);
 }
 
+static JSBool
+swfdec_action_push_string (JSContext *cx, const char *s)
+{
+  JSString *string = JS_NewStringCopyZ (cx, s);
+  if (string == NULL)
+    return JS_FALSE;
+  *cx->fp->sp++ = STRING_TO_JSVAL (string);
+  return JS_TRUE;
+}
+
 /*** ALL THE ACTION IS HERE ***/
 
 static JSBool
@@ -130,9 +198,194 @@ swfdec_action_wait_for_frame (JSContext 
   return JS_TRUE;
 }
 
+static JSBool
+swfdec_action_constant_pool (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+  SwfdecConstantPool *pool;
+
+  pool = swfdec_constant_pool_new_from_action (data, len);
+  if (pool == NULL)
+    return JS_FALSE;
+  if (cx->fp->constant_pool)
+    swfdec_constant_pool_free (cx->fp->constant_pool);
+  cx->fp->constant_pool = pool;
+  return JS_TRUE;
+}
+
+static JSBool
+swfdec_action_push (JSContext *cx, guint stackspace, const guint8 *data, guint len)
+{
+  /* FIXME: supply API for this */
+  SwfdecBits bits;
+
+  swfdec_bits_init_data (&bits, data, len);
+  while (swfdec_bits_left (&bits) && stackspace-- > 0) {
+    guint type = swfdec_bits_get_u8 (&bits);
+    SWFDEC_LOG ("push type %u", type);
+    switch (type) {
+      case 0: /* string */
+	{
+	  const char *s = swfdec_bits_skip_string (&bits);
+	  if (!swfdec_action_push_string (cx, s))
+	    return JS_FALSE;
+	  break;
+	}
+      case 1: /* float */
+	{
+	  double d = swfdec_bits_get_float (&bits);
+	  if (!JS_NewDoubleValue (cx, d, cx->fp->sp))
+	    return JS_FALSE;
+	  cx->fp->sp++;
+	  break;
+	}
+      case 2: /* null */
+	*cx->fp->sp++ = JSVAL_NULL;
+	break;
+      case 3: /* undefined */
+	*cx->fp->sp++ = JSVAL_VOID;
+	break;
+      case 5: /* boolean */
+	*cx->fp->sp++ = swfdec_bits_get_u8 (&bits) ? JSVAL_TRUE : JSVAL_FALSE;
+	break;
+      case 6: /* double */
+	{
+	  double d = swfdec_bits_get_float (&bits);
+	  if (!JS_NewDoubleValue (cx, d, cx->fp->sp))
+	    return JS_FALSE;
+	  cx->fp->sp++;
+	  break;
+	}
+      case 7: /* 32bit int */
+	{
+	  /* FIXME: spec says U32, do they mean this? */
+	  guint i = swfdec_bits_get_u32 (&bits);
+	  *cx->fp->sp++ = INT_TO_JSVAL (i);
+	  break;
+	}
+      case 8: /* 8bit ConstantPool address */
+	{
+	  guint i = swfdec_bits_get_u8 (&bits);
+	  SwfdecConstantPool *pool = cx->fp->constant_pool;
+	  if (pool == NULL) {
+	    SWFDEC_ERROR ("no constant pool to push from");
+	    return JS_FALSE;
+	  }
+	  if (i >= swfdec_constant_pool_size (pool)) {
+	    SWFDEC_ERROR ("constant pool index %u too high - only %u elements",
+		i, swfdec_constant_pool_size (pool));
+	    return JS_FALSE;
+	  }
+	  if (!swfdec_action_push_string (cx, swfdec_constant_pool_get (pool, i)))
+	    return JS_FALSE;
+	  break;
+	}
+      case 9: /* 16bit ConstantPool address */
+	{
+	  guint i = swfdec_bits_get_u16 (&bits);
+	  SwfdecConstantPool *pool = cx->fp->constant_pool;
+	  if (pool == NULL) {
+	    SWFDEC_ERROR ("no constant pool to push from");
+	    return JS_FALSE;
+	  }
+	  if (i >= swfdec_constant_pool_size (pool)) {
+	    SWFDEC_ERROR ("constant pool index %u too high - only %u elements",
+		i, swfdec_constant_pool_size (pool));
+	    return JS_FALSE;
+	  }
+	  if (!swfdec_action_push_string (cx, swfdec_constant_pool_get (pool, i)))
+	    return JS_FALSE;
+	  break;
+	}
+      case 4: /* register */
+      default:
+	SWFDEC_ERROR ("Push: type %u not implemented", type);
+	return JS_FALSE;
+    }
+  }
+  return swfdec_bits_left (&bits) ? JS_TRUE : JS_FALSE;
+}
+
 /*** PRINT FUNCTIONS ***/
 
 static char *
+swfdec_action_print_push (guint action, const guint8 *data, guint len)
+{
+  gboolean first = TRUE;
+  SwfdecBits bits;
+  GString *string = g_string_new ("Push");
+
+  swfdec_bits_init_data (&bits, data, len);
+  while (swfdec_bits_left (&bits)) {
+    guint type = swfdec_bits_get_u8 (&bits);
+    if (first)
+      g_string_append (string, " ");
+    else
+      g_string_append (string, ", ");
+    first = FALSE;
+    switch (type) {
+      case 0: /* string */
+	{
+	  const char *s = swfdec_bits_skip_string (&bits);
+	  if (!s) {
+	    g_string_free (string, TRUE);
+	    return NULL;
+	  }
+	  g_string_append_c (string, '"');
+	  g_string_append (string, s);
+	  g_string_append_c (string, '"');
+	  break;
+	}
+      case 1: /* float */
+	g_string_append_printf (string, "%g", swfdec_bits_get_float (&bits));
+	break;
+      case 2: /* null */
+	g_string_append (string, "null");
+	break;
+      case 3: /* undefined */
+	g_string_append (string, "void");
+	break;
+      case 5: /* boolean */
+	g_string_append (string, swfdec_bits_get_u8 (&bits) ? "True" : "False");
+	break;
+      case 6: /* double */
+	g_string_append_printf (string, "%g", swfdec_bits_get_double (&bits));
+	break;
+      case 7: /* 32bit int */
+	g_string_append_printf (string, "%u", swfdec_bits_get_u32 (&bits));
+      case 8: /* 8bit ConstantPool address */
+	g_string_append_printf (string, "Pool %u", swfdec_bits_get_u8 (&bits));
+	break;
+      case 9: /* 16bit ConstantPool address */
+	g_string_append_printf (string, "Pool %u", swfdec_bits_get_u16 (&bits));
+	break;
+      case 4: /* register */
+      default:
+	SWFDEC_ERROR ("Push: type %u not implemented", type);
+	return JS_FALSE;
+    }
+  }
+  return g_string_free (string, FALSE);
+}
+
+static char *
+swfdec_action_print_constant_pool (guint action, const guint8 *data, guint len)
+{
+  guint i;
+  GString *string;
+  SwfdecConstantPool *pool;
+
+  pool = swfdec_constant_pool_new_from_action (data, len);
+  if (pool == NULL)
+    return JS_FALSE;
+  string = g_string_new ("ConstantPool");
+  for (i = 0; i < swfdec_constant_pool_size (pool); i++) {
+    g_string_append (string, i ? ", " : " ");
+    g_string_append (string, swfdec_constant_pool_get (pool, i));
+  }
+  return g_string_free (string, FALSE);
+}
+
+static char *
 swfdec_action_print_goto_frame (guint action, const guint8 *data, guint len)
 {
   guint frame;
@@ -162,13 +415,14 @@ swfdec_action_print_wait_for_frame (guin
 /* defines minimum and maximum versions for which we have seperate scripts */
 #define MINSCRIPTVERSION 3
 #define MAXSCRIPTVERSION 7
+#define EXTRACT_VERSION(v) MAX ((v) - MINSCRIPTVERSION, MAXSCRIPTVERSION - MINSCRIPTVERSION)
 
 typedef JSBool (* SwfdecActionExec) (JSContext *cx, guint action, const guint8 *data, guint len);
 typedef struct {
   const char *		name;		/* name identifying the action */
   char *		(* print)	(guint action, const guint8 *data, guint len);
   int			remove;		/* values removed from stack or -1 for dynamic */
-  guint			add;		/* values added to the stack */
+  int			add;		/* values added to the stack or -1 for dynamic */
   SwfdecActionExec	exec[MAXSCRIPTVERSION - MINSCRIPTVERSION + 1];
 					/* array is for version 3, 4, 5, 6, 7+ */
 } SwfdecActionSpec;
@@ -270,7 +524,7 @@ static const SwfdecActionSpec actions[25
   [0x83] = { "GetURL", NULL },
   /* version 5 */
   [0x87] = { "StoreRegister", NULL },
-  [0x88] = { "ConstantPool", NULL },
+  [0x88] = { "ConstantPool", swfdec_action_print_constant_pool, 0, 0, { NULL, NULL, swfdec_action_constant_pool, swfdec_action_constant_pool, swfdec_action_constant_pool } },
   /* version 3 */
   [0x8a] = { "WaitForFrame", swfdec_action_print_wait_for_frame, 0, 0, { swfdec_action_wait_for_frame, swfdec_action_wait_for_frame, swfdec_action_wait_for_frame, swfdec_action_wait_for_frame, swfdec_action_wait_for_frame } },
   [0x8b] = { "SetTarget", NULL },
@@ -283,7 +537,7 @@ static const SwfdecActionSpec actions[25
   /* version 5 */
   [0x94] = { "With", NULL },
   /* version 4 */
-  [0x96] = { "Push", NULL },
+  [0x96] = { "Push", swfdec_action_print_push, 0, -1, { NULL, swfdec_action_push, swfdec_action_push, swfdec_action_push, swfdec_action_push } },
   [0x99] = { "Jump", NULL },
   [0x9a] = { "GetURL2", NULL },
   /* version 5 */
@@ -320,7 +574,7 @@ static gboolean
 swfdec_script_foreach (SwfdecBits *bits, SwfdecScriptForeachFunc func, gpointer user_data)
 {
   guint action, len;
-  guint8 *data;
+  const guint8 *data;
 
   while ((action = swfdec_bits_get_u8 (bits))) {
     if (action & 0x80) {
@@ -343,10 +597,19 @@ swfdec_script_foreach (SwfdecBits *bits,
 /*** PUBLIC API ***/
 
 static gboolean
-validate_action (guint action, const guint8 *data, guint len, gpointer script)
+validate_action (guint action, const guint8 *data, guint len, gpointer scriptp)
 {
+  SwfdecScript *script = scriptp;
+  int version = EXTRACT_VERSION (script->version);
+
+  /* ensure there's a function to execute this opcode, otherwise fail */
+  if (actions[action].exec[version] == NULL) {
+    SWFDEC_ERROR ("no opcode for %u %s", action, 
+	actions[action].name ? actions[action].name : "Unknown");
+    return FALSE;
+  }
   /* we might want to do stuff here for certain actions */
-#if 0
+#if 1
   {
     char *foo = swfdec_script_print_action (action, data, len);
     if (foo == NULL)
@@ -361,7 +624,7 @@ SwfdecScript *
 swfdec_script_new (SwfdecBits *bits, const char *name, unsigned int version)
 {
   SwfdecScript *script;
-  guchar *start;
+  const guchar *start;
   
   g_return_val_if_fail (bits != NULL, NULL);
   if (version < MINSCRIPTVERSION) {
@@ -442,7 +705,7 @@ swfdec_script_interpret (SwfdecScript *s
   
   /* set up general stuff */
   swfdec_script_ref (script);
-  version = MAX (script->version - MINSCRIPTVERSION, MAXSCRIPTVERSION - MINSCRIPTVERSION);
+  version = EXTRACT_VERSION (script->version);
   *rval = JSVAL_VOID;
   fp = cx->fp;
   /* set up the script */
@@ -506,9 +769,13 @@ swfdec_script_interpret (SwfdecScript *s
 	  spec->name, spec->remove, fp->sp - fp->spbase);
       goto internal_error;
     }
-    if (fp->sp + spec->add - MAX (spec->remove, 0) > endsp) {
-      SWFDEC_ERROR ("FIXME: implement stack expansion, we got an overflow");
-      goto internal_error;
+    if (spec->add < 0) {
+      action = endsp - fp->sp;
+    } else {
+      if (fp->sp + spec->add - MAX (spec->remove, 0) > endsp) {
+	SWFDEC_ERROR ("FIXME: implement stack expansion, we got an overflow");
+	goto internal_error;
+      }
     }
     ok = spec->exec[version] (cx, action, data, len);
     if (!ok)
@@ -574,6 +841,7 @@ swfdec_script_execute (SwfdecScript *scr
   frame.varobj = obj;
   frame.fun = NULL;
   frame.swf = script;
+  frame.constant_pool = NULL;
   frame.thisp = obj;
   frame.argc = frame.nvars = 0;
   frame.argv = frame.vars = NULL;
@@ -604,6 +872,10 @@ swfdec_script_execute (SwfdecScript *scr
    */
   ok = swfdec_script_interpret (script, cx, &frame.rval);
 
+  /* FIXME: where to clean this up? */
+  if (frame.constant_pool)
+    swfdec_constant_pool_free (frame.constant_pool);
+
   cx->fp = oldfp;
   if (oldfp) {
     g_assert (cx->dormantFrameChain == oldfp);
diff-tree c41b8582293535b64bf83c19843bd4eae8662e6f (from 539f1f3151a6deb4f231f3289d3c8c232eb21bc7)
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Jan 18 12:51:56 2007 +0100

    add the constant pool to the stack frame

diff --git a/libswfdec/js/jsinterp.h b/libswfdec/js/jsinterp.h
index b22166d..88bab68 100644
--- a/libswfdec/js/jsinterp.h
+++ b/libswfdec/js/jsinterp.h
@@ -56,6 +56,7 @@ struct JSStackFrame {
     JSObject        *varobj;        /* variables object, where vars go */
     JSScript        *script;        /* script being interpreted or NULL */
     void	    *swf;	    /* SwfdecScript being executed if script is NULL */
+    void	    *constant_pool; /* constant pool used by SwfdecScript */
     JSFunction      *fun;           /* function being called or null */
     JSObject        *thisp;         /* "this" pointer if in method */
     uintN           argc;           /* actual argument count */
diff-tree 539f1f3151a6deb4f231f3289d3c8c232eb21bc7 (from c3f0eaf5706a0d972132a0ea4fcaff5aa79ec122)
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Jan 18 12:47:17 2007 +0100

    implement swfdec_bits_init_from_data to use SwfdecBits without a buffer
    
    Also make bits.ptr and bits.end const variables.
    This required cleaning up lots of old code that still accessed SwfdecBits directly
    I bet there were a lot of security issues there ;)

diff --git a/libswfdec/swfdec_bits.c b/libswfdec/swfdec_bits.c
index f9f2749..72cc3df 100644
--- a/libswfdec/swfdec_bits.c
+++ b/libswfdec/swfdec_bits.c
@@ -43,6 +43,27 @@ swfdec_bits_init (SwfdecBits *bits, Swfd
   bits->end = buffer->data + buffer->length;
 }
 
+/**
+ * swfdec_bits_init_data:
+ * @bits: the #SwfdecBits to initialize
+ * @data: data to initialize with
+ * @len: length of the data
+ *
+ * Initializes @bits for use with the given @data. All operations on @bits will
+ * return copies of the data, so after use, you can free the supplied data.
+ **/
+void
+swfdec_bits_init_data (SwfdecBits *bits, const guint8 *data, guint len)
+{
+  g_return_if_fail (bits != NULL);
+  g_return_if_fail (data != NULL);
+
+  bits->buffer = NULL;
+  bits->ptr = data;
+  bits->idx = 0;
+  bits->end = bits->ptr + len;
+}
+
 unsigned int 
 swfdec_bits_left (SwfdecBits *b)
 {
@@ -557,7 +578,12 @@ swfdec_bits_get_buffer (SwfdecBits *bits
     if (len == 0)
       return NULL;
   }
-  buffer = swfdec_buffer_new_subbuffer (bits->buffer, bits->ptr - bits->buffer->data, len);
+  if (bits->buffer) {
+    buffer = swfdec_buffer_new_subbuffer (bits->buffer, bits->ptr - bits->buffer->data, len);
+  } else {
+    buffer = swfdec_buffer_new_and_alloc (len);
+    memcpy (buffer->data, bits->ptr, len);
+  }
   bits->ptr += len;
   return buffer;
 }
diff --git a/libswfdec/swfdec_bits.h b/libswfdec/swfdec_bits.h
index 86440f7..08ae1d8 100644
--- a/libswfdec/swfdec_bits.h
+++ b/libswfdec/swfdec_bits.h
@@ -32,13 +32,14 @@ typedef struct _SwfdecBits SwfdecBits;
 
 struct _SwfdecBits
 {
-  SwfdecBuffer *buffer;
-  unsigned char *ptr;
-  unsigned int idx;
-  unsigned char *end;
+  SwfdecBuffer *	buffer;		/* buffer data is taken from or NULL */
+  const unsigned char *	ptr;		/* current location to read from */
+  unsigned int		idx;		/* bits already read from ptr */
+  const unsigned char *	end;		/* pointer after last byte */
 };
 
 void swfdec_bits_init (SwfdecBits *bits, SwfdecBuffer *buffer);
+void swfdec_bits_init_data (SwfdecBits *bits, const guint8 *data, guint len);
 unsigned int swfdec_bits_left (SwfdecBits *b);
 int swfdec_bits_getbit (SwfdecBits * b);
 unsigned int swfdec_bits_getbits (SwfdecBits * b, unsigned int n);
diff --git a/libswfdec/swfdec_codec_screen.c b/libswfdec/swfdec_codec_screen.c
index 305db49..de21d21 100644
--- a/libswfdec/swfdec_codec_screen.c
+++ b/libswfdec/swfdec_codec_screen.c
@@ -140,7 +140,7 @@ swfdec_codec_screen_decode (gpointer cod
       if (inflateReset(&screen->z) != Z_OK) {
 	SWFDEC_ERROR ("error resetting zlib decoder: %s", screen->z.msg);
       }
-      screen->z.next_in = bits.ptr;
+      screen->z.next_in = (void *) bits.ptr;
       if (swfdec_bits_skip_bytes (&bits, size) != size) {
 	SWFDEC_ERROR ("not enough bytes available");
 	return NULL;
diff --git a/libswfdec/swfdec_image.c b/libswfdec/swfdec_image.c
index 6c2dcae..c9df0de 100644
--- a/libswfdec/swfdec_image.c
+++ b/libswfdec/swfdec_image.c
@@ -99,46 +99,30 @@ zfree (void *opaque, void *addr)
   g_free (addr);
 }
 
-static void *
-lossless (void *zptr, int zlen, int *plen)
+static guint8 *
+lossless (const guint8 *zptr, int zlen, int len)
 {
-  void *data;
-  int len;
-  z_stream *z;
+  guint8 *data;
+  z_stream z = { NULL, };
   int ret;
 
-  z = g_new0 (z_stream, 1);
-  z->zalloc = zalloc;
-  z->zfree = zfree;
-  z->opaque = NULL;
-
-  z->next_in = zptr;
-  z->avail_in = zlen;
-
-  data = NULL;
-  len = 0;
-  ret = inflateInit (z);
-  while (z->avail_in > 0) {
-    if (z->avail_out == 0) {
-      len += 1024;
-      data = g_realloc (data, len);
-      z->next_out = data + z->total_out;
-      z->avail_out += 1024;
-    }
-    ret = inflate (z, Z_SYNC_FLUSH);
-    if (ret != Z_OK)
-      break;
-  }
+  z.zalloc = zalloc;
+  z.zfree = zfree;
+  z.opaque = NULL;
+
+  data = g_malloc (len);
+  z.next_in = (Bytef *) zptr;
+  z.avail_in = zlen;
+  z.next_out = data;
+  z.avail_out = len;
+
+  ret = inflateInit (&z);
+  ret = inflate (&z, Z_SYNC_FLUSH);
   if (ret != Z_STREAM_END) {
     SWFDEC_WARNING ("lossless: ret == %d", ret);
   }
+  inflateEnd (&z);
 
-  if (plen)
-    (*plen) = z->total_out;
-
-  inflateEnd (z);
-
-  g_free (z);
   return data;
 }
 
@@ -278,11 +262,8 @@ int
 tag_func_define_bits_jpeg_3 (SwfdecSwfDecoder * s)
 {
   SwfdecBits *bits = &s->b;
-  int id;
+  guint id;
   SwfdecImage *image;
-  unsigned char *endptr;
-
-  endptr = bits->ptr + bits->buffer->length;
 
   id = swfdec_bits_get_u16 (bits);
   SWFDEC_LOG ("  id = %d", id);
@@ -292,9 +273,7 @@ tag_func_define_bits_jpeg_3 (SwfdecSwfDe
     return SWFDEC_STATUS_OK;
 
   image->type = SWFDEC_IMAGE_TYPE_JPEG3;
-  image->raw_data = swfdec_buffer_ref (bits->buffer);
-
-  bits->ptr += bits->buffer->length - 2;
+  image->raw_data = swfdec_bits_get_buffer (bits, -1);
 
   return SWFDEC_STATUS_OK;
 }
@@ -306,21 +285,20 @@ swfdec_image_jpeg3_load (SwfdecImage *im
   unsigned char *image_data;
   unsigned char *alpha_data;
   SwfdecBits bits;
-  int len;
+  SwfdecBuffer *buffer;
   int jpeg_length;
 
-  bits.buffer = image->raw_data;
-  bits.ptr = image->raw_data->data;
-  bits.idx = 0;
-  bits.end = bits.ptr + image->raw_data->length;
-
-  bits.ptr += 2;
+  swfdec_bits_init (&bits, image->raw_data);
 
   jpeg_length = swfdec_bits_get_u32 (&bits);
+  buffer = swfdec_bits_get_buffer (&bits, jpeg_length);
+  if (buffer == NULL)
+    return;
 
   dec = jpeg_rgb_decoder_new ();
 
-  jpeg_rgb_decoder_addbits (dec, bits.ptr, jpeg_length);
+  jpeg_rgb_decoder_addbits (dec, buffer->data, buffer->length);
+  swfdec_buffer_unref (buffer);
   jpeg_rgb_decoder_parse (dec);
   jpeg_rgb_decoder_get_image_size (dec, &image->width, &image->height);
   if (image->width == 0 || image->height == 0) {
@@ -332,9 +310,9 @@ swfdec_image_jpeg3_load (SwfdecImage *im
       &image->rowstride, &image->width, &image->height);
   jpeg_rgb_decoder_free (dec);
 
-  bits.ptr += jpeg_length;
-
-  alpha_data = lossless (bits.ptr, bits.end - bits.ptr, &len);
+  buffer = swfdec_bits_get_buffer (&bits, -1);
+  alpha_data = lossless (buffer->data, buffer->length, image->width * image->height);
+  swfdec_buffer_unref (buffer);
 
   merge_alpha (image, image_data, alpha_data);
   g_free (alpha_data);
@@ -372,19 +350,12 @@ swfdec_image_lossless_load (SwfdecImage 
   int format;
   int color_table_size;
   unsigned char *ptr;
-  int len;
   unsigned char *endptr;
   SwfdecBits bits;
   unsigned char *image_data = NULL;
   int have_alpha = (image->type == SWFDEC_IMAGE_TYPE_LOSSLESS2);
 
-  bits.buffer = image->raw_data;
-  bits.ptr = image->raw_data->data;
-  bits.idx = 0;
-  bits.end = bits.ptr + image->raw_data->length;
-  endptr = bits.ptr + bits.buffer->length;
-
-  bits.ptr += 2;
+  swfdec_bits_init (&bits, image->raw_data);
 
   format = swfdec_bits_get_u8 (&bits);
   SWFDEC_LOG ("  format = %d", format);
@@ -406,7 +377,7 @@ swfdec_image_lossless_load (SwfdecImage 
   if (image->width == 0 || image->height == 0)
     return;
   swfdec_cached_load (SWFDEC_CACHED (image), 4 * image->width * image->height);
-  ptr = lossless (bits.ptr, endptr - bits.ptr, &len);
+  ptr = lossless (bits.ptr, endptr - bits.ptr, image->width * image->height);
   bits.ptr = endptr;
 
   if (format == 3) {
@@ -531,9 +502,8 @@ tag_func_define_bits_lossless (SwfdecSwf
     return SWFDEC_STATUS_OK;
 
   image->type = SWFDEC_IMAGE_TYPE_LOSSLESS;
-  image->raw_data = swfdec_buffer_ref (bits->buffer);
+  image->raw_data = swfdec_bits_get_buffer (bits, -1);
 
-  bits->ptr += bits->buffer->length - 2;
   return SWFDEC_STATUS_OK;
 }
 
@@ -552,9 +522,7 @@ tag_func_define_bits_lossless_2 (SwfdecS
     return SWFDEC_STATUS_OK;
 
   image->type = SWFDEC_IMAGE_TYPE_LOSSLESS2;
-  image->raw_data = swfdec_buffer_ref (bits->buffer);
-
-  bits->ptr += bits->buffer->length - 2;
+  image->raw_data = swfdec_bits_get_buffer (bits, -1);
 
   return SWFDEC_STATUS_OK;
 }
diff --git a/libswfdec/swfdec_swf_decoder.c b/libswfdec/swfdec_swf_decoder.c
index e7be205..a43c9ac 100644
--- a/libswfdec/swfdec_swf_decoder.c
+++ b/libswfdec/swfdec_swf_decoder.c
@@ -239,7 +239,7 @@ swfdec_swf_decoder_parse (SwfdecDecoder 
 {
   SwfdecSwfDecoder *s = SWFDEC_SWF_DECODER (dec);
   int ret = SWFDEC_STATUS_OK;
-  unsigned char *endptr;
+  const unsigned char *endptr;
   SwfdecBuffer *buffer;
 
   s->b = s->parse;
diff --git a/libswfdec/swfdec_tag.c b/libswfdec/swfdec_tag.c
index 4f57b1a..3896101 100644
--- a/libswfdec/swfdec_tag.c
+++ b/libswfdec/swfdec_tag.c
@@ -212,7 +212,6 @@ tag_func_define_sprite (SwfdecSwfDecoder
 
   s->parse_sprite = sprite;
   while (1) {
-    unsigned char *endptr;
     int x;
     int tag;
     guint tag_len;
@@ -258,7 +257,7 @@ tag_func_define_sprite (SwfdecSwfDecoder
       SWFDEC_ERROR ("invalid tag %d %s during DefineSprite",
           tag, swfdec_swf_decoder_get_tag_name (tag));
     } else {
-      endptr = parse.ptr + tag_len;
+      const unsigned char *endptr = parse.ptr + tag_len;
       ret = func (s);
 
       swfdec_bits_syncbits (bits);
@@ -311,22 +310,11 @@ int
 tag_func_do_init_action (SwfdecSwfDecoder * s)
 {
   SwfdecBits *bits = &s->b;
-  int len;
   SwfdecBuffer *buffer;
   SwfdecCharacter *character;
-  unsigned char *endptr;
-  //int retcode = SWF_ERROR;
-
-  endptr = bits->ptr + bits->buffer->length;
 
   character = swfdec_swf_decoder_get_character (s, swfdec_bits_get_u16 (bits));
-
-  len = bits->end - bits->ptr;
-
-  buffer = swfdec_buffer_new_subbuffer (bits->buffer,
-    bits->ptr - bits->buffer->data, len);
-
-  bits->ptr += len;
+  buffer = swfdec_bits_get_buffer (bits, -1);
 
   if (SWFDEC_IS_SPRITE (character)) {
     SWFDEC_WARNING ("init actions not implemented yet");
@@ -339,7 +327,6 @@ tag_func_do_init_action (SwfdecSwfDecode
   }
   swfdec_buffer_unref (buffer);
 
-  //return retcode;
   return SWFDEC_STATUS_OK;
 }
 
@@ -389,11 +376,8 @@ tag_func_define_button_2 (SwfdecSwfDecod
   int flags;
   int offset;
   SwfdecButton *button;
-  unsigned char *endptr;
   char *script_name;
 
-  endptr = bits->ptr + bits->buffer->length;
-
   id = swfdec_bits_get_u16 (bits);
   button = swfdec_swf_decoder_create_character (s, id, SWFDEC_TYPE_BUTTON);
   if (!button)
@@ -476,11 +460,8 @@ tag_func_define_button (SwfdecSwfDecoder
   SwfdecBits *bits = &s->b;
   int id;
   SwfdecButton *button;
-  unsigned char *endptr;
   char *script_name;
 
-  endptr = bits->ptr + bits->buffer->length;
-
   id = swfdec_bits_get_u16 (bits);
   button = swfdec_swf_decoder_create_character (s, id, SWFDEC_TYPE_BUTTON);
   if (!button)


More information about the Swfdec mailing list