[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