1 /****************************************************************************
2  *
3  *  Copyright (C) 2006,2007 A.Kleine
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  ****************************************************************************/
20 
21 #define _GNU_SOURCE 1
22 
23 #define DEBUGSTACK
24 #define DECOMP_SWITCH
25 // #define DEBUGSWITCH
26 
27 //#define STATEMENT_CLASS
28 //  I have uncommented some buggy class recognition stuff in decompileIF()
29 //  to make work simple code lines like:  "if(!a) trace(a);"   - ak, November 2006
30 
31 //  To do: add some free()-calls for allocated blocks
32 
33 #include <assert.h>
34 
35 #include <stdlib.h>
36 #include <stdarg.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <math.h>
40 
41 #include "read.h"
42 #include "action.h"
43 #include "swftypes.h"
44 #include "../src/blocks/error.h"
45 #include "vasprintf.h"
46 
47 
48 static char **pool;
49 struct SWF_ACTIONPUSHPARAM *regs[256];
50 
51 static char *getName(struct SWF_ACTIONPUSHPARAM *act);
52 
53 static int offseoloop;	// offset wherever a break can jump to (loops and switch)
54 
55 static void
dumpRegs()56 dumpRegs()
57 {
58 int i;
59 for(i=0;i<6;i++)
60 	if( regs[i] )
61 		printf("reg[%d] %s\n", i, getName(regs[i]));
62 }
63 
64 /*
65  * Start Package
66  *
67  * A package to build up a string that can be returned to the caller
68  * ak/2006: Extended for temporary swichting to a 2nd buffer
69  */
70 #define USE_LIB 1
71 
72 static int strsize=0;
73 static int strmaxsize=0;
74 static char *dcstr=NULL;
75 static char *dcptr=NULL;
76 
77 #define DCSTRSIZE 40960
78 #define PARAM_STRSIZE 512
79 void
dcinit()80 dcinit()
81 {
82 	strsize=0;
83 	strmaxsize=DCSTRSIZE;
84 	dcstr=calloc(DCSTRSIZE,1);
85 	dcptr=dcstr;
86 }
87 
88 void
dcchkstr(int size)89 dcchkstr(int size)
90 {
91 	while( (strsize+size) > strmaxsize ) {
92 		dcstr=realloc(dcstr,strmaxsize+DCSTRSIZE);
93 		strmaxsize+=DCSTRSIZE;
94 		dcptr=dcstr+strsize;
95 	}
96 
97 }
98 
99 void
dcputs(const char * s)100 dcputs(const char *s)
101 {
102 	int len=strlen(s);
103 	dcchkstr(len);
104 	strcat(dcptr,s);
105 	dcptr+=len;
106 	strsize+=len;
107 }
108 
109 void
dcputchar(char c)110 dcputchar(char c)
111 {
112 	dcchkstr(1);
113 
114 	*dcptr++=c;
115 	*dcptr='\000';
116 	strsize++;
117 }
118 
119 int
dcprintf(char * format,...)120 dcprintf(char *format, ...)
121 {
122 	char *s;
123 	size_t size;
124 	int ret;
125 
126 	va_list args;
127 	va_start(args,format);
128 	ret = vasprintf(&s,format,args);
129 	dcputs(s);
130 	size=strlen(s);
131 	free(s);
132 	return size;
133 }
134 
135 char *
dcgetstr()136 dcgetstr()
137 {
138 	char *ret;
139 	ret = dcstr;
140 	dcstr=NULL;
141 	strmaxsize=0;
142 	return ret;
143 }
144 
145 struct strbufinfo
146 {
147 	int size;
148 	int maxsize;
149 	char *str;
150 	char *ptr;
151 };
152 
153 
setTempString(void)154 static struct strbufinfo setTempString(void)
155 {
156 	struct strbufinfo current;
157 	current.size=strsize;
158 	current.maxsize=strmaxsize;
159 	current.str=dcstr;
160 	current.ptr=dcptr;
161 	dcinit();
162 	return current;
163 }
164 
setOrigString(struct strbufinfo old)165 static void setOrigString(struct strbufinfo old)
166 {
167 	free(dcstr);				/* not needed anymore */
168 	strsize=old.size;
169 	strmaxsize=old.maxsize;
170 	dcstr=old.str;
171 	dcptr=old.ptr;
172 }
173 
174 // a variant of setOrigString()
175 // but for further usage of 2nd buffer
176 //
177 static char *
switchToOrigString(struct strbufinfo old)178 switchToOrigString(struct strbufinfo old)
179 {
180 	char *tmp=dcstr;
181 	strsize=old.size;
182 	strmaxsize=old.maxsize;
183 	dcstr=old.str;
184 	dcptr=old.ptr;
185 	return tmp;
186 }
187 
188 #if USE_LIB
189 #define puts(s) dcputs(s)
190 #define putchar(c) dcputchar(c)
191 #define printf dcprintf
192 #endif
193 
194 #define INDENT { int ii=gIndent; while(--ii>=0) { putchar(' '); putchar(' '); } }
195 
196 /* String used for terminating lines (see println) */
197 static const char* newlinestring = "\\\n";
198 
199 /* Set the newline character. By default it is an escaped NL. */
200 void
setNewLineString(const char * ch)201 setNewLineString(const char* ch)
202 {
203 	newlinestring = ch;
204 }
205 
206 /* Print a line with a terminating newline, which can be set by
207  * setNewLineString()
208  */
209 static void
println(const char * fmt,...)210 println(const char* fmt, ...)
211 {
212 	char *tmp;
213 	int written;
214 
215 	va_list ap;
216 	va_start (ap, fmt);
217 	written = vasprintf (&tmp, fmt, ap);
218 
219 	dcprintf("%s%s", tmp, newlinestring);
220 
221 	free(tmp);
222 }
223 
224 
225 /* End Package */
226 
227 /*
228  * Start Package
229  *
230  * A package to maintain escaped characters strings
231  * [ BSC == BackSlashCounter ]
232  */
233 #define BSC 2
strlenext(char * str)234 static int strlenext(char *str)
235 {
236 	int i=0;
237 	while (*str)
238 	{
239 		i++;
240 		if (*str=='\'') i+=BSC;
241 			str++;
242 	}
243 	return i;
244 }
245 
strcpyext(char * dest,char * src)246 static char* strcpyext(char *dest,char *src)
247 {
248 	char *r=dest;
249 	while (*src)
250 	{
251 		if (*src=='\'')
252 		{
253 			*dest++='\\';
254 #if BSC == 2
255 			*dest++='\\';
256 #endif
257 		}
258 		*dest++=*src++;
259 	}
260 	*dest='\0';
261 	return r;
262 }
263 
strcatext(char * dest,char * src)264 static char* strcatext(char *dest,char *src)
265 {
266 	char *r=dest;
267 	while (*dest)
268 		dest++;
269 	strcpyext(dest,src);
270 	return r;
271 }
272 /* End Package */
273 
274 /*
275  * Start Package
276  *
277  * A package to maintain a representation of the Flash VM stack
278  */
279 
280 struct _stack {
281 	char type;
282 	struct SWF_ACTIONPUSHPARAM *val;
283 	struct _stack *next;
284 };
285 
286 struct _stack *Stack;
287 
288 enum
289 {
290 	PUSH_STRING = 0,
291 	PUSH_FLOAT = 1,
292 	PUSH_NULL = 2,
293 	PUSH_UNDEF = 3,
294 	PUSH_REGISTER = 4,
295 	PUSH_BOOLEAN = 5,
296 	PUSH_DOUBLE = 6,
297 	PUSH_INT = 7,
298 	PUSH_CONSTANT = 8,
299 	PUSH_CONSTANT16 = 9,
300 	PUSH_VARIABLE = 10,
301 };
302 
303 static char *
getString(struct SWF_ACTIONPUSHPARAM * act)304 getString(struct SWF_ACTIONPUSHPARAM *act)
305 {
306 	char *t;
307 #ifdef DEBUG
308 	printf("*getString* type=%d\n",act->Type);
309 #endif
310 	switch( act->Type )
311 	{
312 	case PUSH_STRING:
313 		t=malloc(strlen(act->p.String)+3); /* 2 "'"s and a NULL */
314 		strcpy(t,"'");
315 		strcat(t,act->p.String);
316 		strcat(t,"'");
317 		return t;
318 	case PUSH_NULL: /* NULL */
319 		return "null";
320 	case PUSH_UNDEF: /* Undefined */
321 		return "undefined";
322 	case PUSH_REGISTER: /* REGISTER */
323 		if( regs[act->p.RegisterNumber] &&
324 		    regs[act->p.RegisterNumber]->Type != 4 &&
325 		    regs[act->p.RegisterNumber]->Type != 7 )
326 		{
327 			return getName(regs[act->p.RegisterNumber]);
328 		}
329 		else
330 		{
331 			t=malloc(4); /* Rdd */
332 			sprintf(t,"R%d", act->p.RegisterNumber );
333 			return t;
334 		}
335 	case PUSH_BOOLEAN: /* BOOLEAN */
336 		if( act->p.Boolean )
337 			return "true";
338 		else
339 			return "false";
340 	case PUSH_DOUBLE: /* DOUBLE */
341 		t=malloc(10); /* big enough? */
342 		sprintf(t,"%g", act->p.Double );
343 		return t;
344 	case PUSH_INT: /* INTEGER */
345 		t=malloc(10); /* 32-bit decimal */
346 		sprintf(t,"%ld", act->p.Integer );
347 		return t;
348 	case PUSH_CONSTANT: /* CONSTANT8 */
349 		t=malloc(strlenext(pool[act->p.Constant8])+3); /* 2 "'"s and a NULL */
350 		strcpy(t,"'");
351 		strcatext(t,pool[act->p.Constant8]);
352 		strcat(t,"'");
353 		return t;
354 	case PUSH_CONSTANT16: /* CONSTANT16 */
355 		t=malloc(strlenext(pool[act->p.Constant16])+3); /* 2 '\"'s and a NULL */
356 		strcpy(t,"'");
357 		strcatext(t,pool[act->p.Constant16]);
358 		strcat(t,"'");
359 		return t;
360 
361 	case 12:
362 	case 11: /* INCREMENTED or DECREMENTED VARIABLE */
363 	case PUSH_VARIABLE: /* VARIABLE */
364 		return act->p.String;
365 	default:
366 		fprintf (stderr,"  Can't get string for type: %d\n", act->Type);
367 		break;
368 	}
369 	return "";
370 }
371 
372 static char *
getName(struct SWF_ACTIONPUSHPARAM * act)373 getName(struct SWF_ACTIONPUSHPARAM *act)
374 {
375 	char *t;
376 
377 	switch( act->Type )
378 	{
379 	case PUSH_STRING: /* STRING */
380 		t=malloc(strlen(act->p.String)+3);
381 		/*
382 		strcpy(t,"\"");
383 		strcat(t,act->p.String);
384 		strcat(t,"\"");
385 		*/
386 		strcpy(t,act->p.String);
387 		if(strlen(t)) /* Not a zero length string */
388 			return t;
389 		else
390 			return "this";
391 #if 0
392 	  case 4: /* REGISTER */
393                 t=malloc(4); /* Rdd */
394   		sprintf(t,"R%d", act->p.RegisterNumber );
395   		return t;
396 #endif
397 	case PUSH_CONSTANT: /* CONSTANT8 */
398 		t=malloc(strlenext(pool[act->p.Constant8])+1);
399 		strcpyext(t,pool[act->p.Constant8]);
400 		if(strlen(t)) /* Not a zero length string */
401 			return t;
402 		else
403 		{
404 			t=realloc(t,6);
405 			return strcpy(t,"this");
406 		}
407 	case PUSH_CONSTANT16: /* CONSTANT16 */
408 		t=malloc(strlenext(pool[act->p.Constant16])+1);
409 		strcpyext(t,pool[act->p.Constant16]);
410 		if(strlen(t)) /* Not a zero length string */
411 			return t;
412 		else
413 		{
414 			t=realloc(t,6);
415 			return strcpy(t,"this");
416 		}
417 	default:
418 		return getString(act);
419 	}
420 }
421 
422 static int
getInt(struct SWF_ACTIONPUSHPARAM * act)423 getInt(struct SWF_ACTIONPUSHPARAM *act)
424 {
425 	switch( act->Type )
426 	{
427 	case PUSH_FLOAT: /* FLOAT -- also used for PROPERTY storing */
428 		return ((int)act->p.Float);
429 	case PUSH_NULL: /* NULL */
430 		return 0;
431 	case PUSH_REGISTER: /* REGISTER */
432 		return getInt(regs[act->p.RegisterNumber]);
433 	case PUSH_DOUBLE: /* DOUBLE */
434 		return (int)act->p.Double;
435 	case PUSH_INT: /* INTEGER */
436 		return act->p.Integer;
437 	default:
438 		fprintf (stderr,"  Can't get int for type: %d\n", act->Type);
439 	}
440 	return 0;
441 }
442 
443 static char *
getProperty(Property prop)444 getProperty(Property prop)
445 {
446 	switch(prop)
447 	{
448 	case SWF_SETPROPERTY_X: 	return("_x"); break;
449 	case SWF_SETPROPERTY_Y:
450 	case PROPERTY_Y:		return("_y"); break;
451 	case PROPERTY_XMOUSE:		return("_xMouse"); break;
452 	case PROPERTY_YMOUSE:		return("_yMouse"); break;
453 	case SWF_SETPROPERTY_XSCALE:
454 	case PROPERTY_XSCALE:	   	return("_xScale"); break;
455 	case SWF_SETPROPERTY_YSCALE:
456 	case PROPERTY_YSCALE:	   	return("_yScale"); break;
457 	case PROPERTY_CURRENTFRAME:	return("_currentFrame"); break;
458 	case PROPERTY_TOTALFRAMES:	return("_totalFrames"); break;
459 	case SWF_SETPROPERTY_ALPHA:
460 	case PROPERTY_ALPHA:		return("_alpha"); break;
461 	case SWF_SETPROPERTY_VISIBILITY:
462 	case PROPERTY_VISIBLE:		return("_visible"); break;
463 	case PROPERTY_WIDTH:		return("_width"); break;
464 	case PROPERTY_HEIGHT:		return("_height"); break;
465 	case SWF_SETPROPERTY_ROTATION:
466 	case PROPERTY_ROTATION:		return("_rotation"); break;
467 	case PROPERTY_TARGET:		return("_target"); break;
468 	case PROPERTY_FRAMESLOADED:	return("_framesLoaded"); break;
469 	case SWF_SETPROPERTY_NAME:
470 	case PROPERTY_NAME:		return("_name"); break;
471 	case PROPERTY_DROPTARGET:	return("_dropTarget"); break;
472 	case PROPERTY_URL:		return("_url"); break;
473 	case SWF_SETPROPERTY_HIGHQUALITY:
474 	case PROPERTY_HIGHQUALITY:	return("_quality"); break;
475 	case SWF_SETPROPERTY_SHOWFOCUSRECT:
476 	case PROPERTY_FOCUSRECT:	return("_focusRect"); break;
477 	case SWF_SETPROPERTY_SOUNDBUFFERTIME:
478 	case PROPERTY_SOUNDBUFTIME:	return("_soundBufTime"); break;
479 	case SWF_SETPROPERTY_WTHIT:
480 	case PROPERTY_WTHIT:		return("_WTHIT!?"); break;
481 	default:			return("unknown property!"); break;
482 	}
483 }
484 
485 struct SWF_ACTIONPUSHPARAM *
newVar(char * var)486 newVar(char *var)
487 {
488 	struct SWF_ACTIONPUSHPARAM *v;
489 
490 	v=malloc(sizeof(struct SWF_ACTIONPUSHPARAM));
491 	v->Type = PUSH_VARIABLE;
492 	v->p.String = var;
493 	return v;
494 }
495 
496 struct SWF_ACTIONPUSHPARAM *
newVar2(char * var,char * var2)497 newVar2(char *var,char *var2)
498 {
499 	struct SWF_ACTIONPUSHPARAM *v;
500 
501 	v=malloc(sizeof(struct SWF_ACTIONPUSHPARAM));
502 	v->Type = PUSH_VARIABLE;
503 	v->p.String = malloc(strlen(var)+strlen(var2)+1);
504 	strcpy(v->p.String,var);
505 	strcat(v->p.String,var2);
506 	return v;
507 }
508 
509 
510 struct SWF_ACTIONPUSHPARAM *
newVar3(char * var,char * var2,char * var3)511 newVar3(char *var,char *var2, char *var3)
512 {
513 	struct SWF_ACTIONPUSHPARAM *v;
514 
515 	v=malloc(sizeof(struct SWF_ACTIONPUSHPARAM));
516 	v->Type = PUSH_VARIABLE; /* VARIABLE */
517 	v->p.String = malloc(strlen(var)+strlen(var2)+strlen(var3)+1);
518 	strcpy(v->p.String,var);
519 	strcat(v->p.String,var2);
520 	strcat(v->p.String,var3);
521 	return v;
522 }
523 
524 struct SWF_ACTIONPUSHPARAM *
newVar5(char * var,char * var2,char * var3,char * var4,char * var5)525 newVar5(char *var,char *var2, char *var3,char *var4,char *var5)
526 {
527 	struct SWF_ACTIONPUSHPARAM *v;
528 
529 	v=malloc(sizeof(struct SWF_ACTIONPUSHPARAM));
530 	v->Type = PUSH_VARIABLE; /* VARIABLE */
531 	v->p.String = malloc(strlen(var)+strlen(var2)+strlen(var3)+strlen(var4)+strlen(var5)+1);
532 	strcpy(v->p.String,var);
533 	strcat(v->p.String,var2);
534 	strcat(v->p.String,var3);
535 	strcat(v->p.String,var4);
536 	strcat(v->p.String,var5);
537 	return v;
538 }
539 
540 void
push(struct SWF_ACTIONPUSHPARAM * val)541 push(struct SWF_ACTIONPUSHPARAM *val)
542 {
543 	struct _stack *t;
544 #ifdef DEBUG
545 	printf("*push* type=%d\n",val->Type);
546 #endif
547 	t = calloc(1,sizeof(*Stack));
548 	t->type = val->Type;
549 	t->val = val;
550 	t->next = Stack;
551 	Stack = t;
552 }
553 
554 
555 void
pushdup()556 pushdup()
557 {
558 	struct _stack *t;
559 #ifdef DEBUG
560 	printf("*pushdup*\n");
561 #endif
562 	if(Stack == NULL)
563 	{
564 		SWF_warn("WARNING: pushdup on empty stack. This might be wrong!\n");
565 		return;
566 	}
567 	t = calloc(1,sizeof(*Stack));
568 	t->type = Stack->type;
569 	t->val =  Stack->val;
570 	t->next = Stack;
571 	Stack = t;
572 }
573 
574 
575 void
pushvar(struct SWF_ACTIONPUSHPARAM * val)576 pushvar(struct SWF_ACTIONPUSHPARAM *val)
577 {
578 	struct _stack *t;
579 #ifdef DEBUG
580 	printf("*pushvar*\n");
581 #endif
582 	t = calloc(1,sizeof(*Stack));
583 	t->type = 'v'; // ???
584 	t->val = val;
585 	t->next = Stack;
586 	Stack = t;
587 }
588 
pop()589 struct SWF_ACTIONPUSHPARAM * pop()
590 {
591 	struct _stack *t;
592 	struct SWF_ACTIONPUSHPARAM * ret;
593 
594 #ifdef DEBUG
595 	printf("*pop*\n");
596 #endif
597 #ifdef DEBUGSTACK		/* continue w stack dummy */
598 	if( Stack == NULL ) push(newVar("// *** pop(): INTERNAL STACK ERROR FOUND ***"));
599 #else
600 	if( Stack == NULL ) SWF_error("Stack blown!! - pop");
601 #endif
602 	t=Stack;
603 	Stack=t->next;
604 	ret=t->val;
605 	return ret;
606 }
607 
peek()608 struct SWF_ACTIONPUSHPARAM * peek()
609 {
610 #ifdef DEBUG
611 	printf("*peek*\n");
612 #endif
613 #ifdef DEBUGSTACK		/* continue w stack dummy */
614 	if( Stack == NULL ) push(newVar("// *** peek(): INTERNAL STACK ERROR FOUND ***"));
615 #else
616 	if( Stack == NULL ) SWF_error("Stack blown!! - peek");
617 #endif
618 	return Stack->val;
619 }
620 
621 void
stackswap()622 stackswap()
623 {
624 #ifdef DEBUG
625 	printf("*stackswap*\n");
626 #endif
627 	struct SWF_ACTIONPUSHPARAM *p = peek();		/* peek() includes error handling */
628 	char type = Stack->type;
629 	Stack->type = Stack->next->type;
630 	Stack->val  = Stack->next->val;
631 	Stack->next->type = type;
632 	Stack->next->val  = p;
633 }
634 
635 
636 static struct SWF_ACTIONPUSHPARAM *
newVar_N(char * var,char * var2,char * var3,char * var4,int pop_counter,char * final)637 newVar_N(char *var,char *var2, char *var3,char *var4,int pop_counter,char *final)
638 {
639 	struct SWF_ACTIONPUSHPARAM *v;
640 	int psize=PARAM_STRSIZE;
641 	int i;
642 	int slen=strlen(var)+strlen(var2)+strlen(var3)+strlen(var4)+strlen(final);
643 
644 	v=malloc(sizeof(struct SWF_ACTIONPUSHPARAM));
645 	v->p.String = malloc(psize + slen);
646 	v->Type = PUSH_VARIABLE;
647 	strcpy(v->p.String,var);
648 	strcat(v->p.String,var2);
649 	strcat(v->p.String,var3);
650 	strcat(v->p.String,var4);
651 	for(i=0;i<pop_counter;i++)
652 	{
653 		char *pops=getString(pop());
654 		while ( strlen(v->p.String)+ 2 + strlen(pops) +slen >= psize)
655 		{
656 			psize += PARAM_STRSIZE;
657 			v->p.String = realloc( v->p.String, psize);
658 		}
659 		strcat(v->p.String,pops);
660 		if( i < pop_counter-1 )
661 			strcat(v->p.String,",");
662 	}
663 	strcat(v->p.String,final);
664 	return v;
665 }
666 
667 // similar to newVar_N(),
668 // but pops 2 items from stack per counter,
669 // and second of them we are interested in getName() instead of getString()
670 static struct SWF_ACTIONPUSHPARAM *
newVar_N2(char * var,char * var2,char * var3,char * var4,int pop_counter,char * final)671 newVar_N2(char *var,char *var2, char *var3,char *var4,int pop_counter,char *final)
672 {
673 	struct SWF_ACTIONPUSHPARAM *v;
674 	int psize=PARAM_STRSIZE;
675 	int i;
676 	int slen=strlen(var)+strlen(var2)+strlen(var3)+strlen(var4)+strlen(final);
677 
678 	v=malloc(sizeof(struct SWF_ACTIONPUSHPARAM));
679 	v->p.String = malloc(psize + slen);
680 	v->Type = PUSH_VARIABLE;
681 	strcpy(v->p.String,var);
682 	strcat(v->p.String,var2);
683 	strcat(v->p.String,var3);
684 	strcat(v->p.String,var4);
685 	for(i=0;i<pop_counter;i++)
686 	{
687 		char *pops1=getString(pop());
688 		char *pops2=getName  (pop());
689 
690 		while ( strlen(v->p.String)+ 3 + strlen(pops1)+ strlen(pops2) +slen >= psize)
691 		{
692 			psize += PARAM_STRSIZE;
693 			v->p.String = realloc( v->p.String, psize);
694 		}
695 		strcat(v->p.String,pops2);
696 		strcat(v->p.String,":");
697 		strcat(v->p.String,pops1);
698 		if( i < pop_counter-1 )
699 			strcat(v->p.String,",");
700 	}
701 	strcat(v->p.String,final);
702 	return v;
703 }
704 
705 /* End Package */
706 
707 static int gIndent;
708 static void decompileActions(int n, SWF_ACTION *actions,int indent);
709 char * decompile5Action(int n, SWF_ACTION *actions,int indent);
710 
711 /******************************************************************************/
712 /******************************************************************************/
713 /******************************************************************************/
714 /******************************************************************************/
715 /******************************************************************************/
716 
717 
718 #define SanityCheck(curact,test,msg ) \
719     if(!(test) ) SWF_error( "SanityCheck failed in %s\n %s\n", #curact, msg );
720 
721 #define OUT_BEGIN(block) \
722 	                struct block *sact = (struct block *)act;
723 #define OUT_BEGIN2(block) \
724 	                struct block *sact = (struct block *)&(actions[n]);
725 
726 static void
decompileCONSTANTPOOL(SWF_ACTION * act)727 decompileCONSTANTPOOL (SWF_ACTION *act)
728 {
729 	OUT_BEGIN(SWF_ACTIONCONSTANTPOOL);
730 	pool=sact->ConstantPool;
731 }
732 
733 static void
decompileWAITFORFRAME(SWF_ACTION * act)734 decompileWAITFORFRAME (SWF_ACTION *act)
735 {
736 	OUT_BEGIN(SWF_ACTIONWAITFORFRAME);
737 
738 	INDENT
739 	println("WaitForFrame(%d,%d);", sact->Frame,sact->SkipCount);
740 }
741 
742 static void
decompilePUSHPARAM(struct SWF_ACTIONPUSHPARAM * act,int wantstring)743 decompilePUSHPARAM (struct SWF_ACTIONPUSHPARAM *act, int wantstring)
744 {
745 	char *t;
746 	switch( act->Type )
747 	{
748 	case PUSH_STRING: /* STRING */
749 		if( wantstring ) printf ("'%s'", act->p.String);
750 		else printf ("%s", act->p.String);
751 		break;
752 	case PUSH_FLOAT: /* FLOAT */
753 		printf ("%f", act->p.Float);
754 		break;
755 	case PUSH_NULL: /* NULL */
756 		printf ("NULL" );
757 		break;
758 	case PUSH_UNDEF: /* Undefined */
759 		printf ("undefined" );
760 		break;
761 	case PUSH_REGISTER: /* Register */
762 		if( regs[act->p.RegisterNumber] ) {
763 			printf ("%s", getName(act));
764 		} else {
765 			printf ("R%d", (int)act->p.RegisterNumber);
766 		}
767 		break;
768 	case PUSH_BOOLEAN: /* BOOLEAN */
769 		printf ("%s", act->p.Boolean?"true":"false");
770 		break;
771 	case PUSH_DOUBLE: /* DOUBLE */
772 		printf ("%g", act->p.Double);
773 		break;
774 	case PUSH_INT: /* INTEGER */
775 		printf ("%ld", act->p.Integer);
776 		break;
777 
778 	case PUSH_CONSTANT: /* CONSTANT8 */
779 	case PUSH_CONSTANT16: /* CONSTANT16 */
780 		if( wantstring ) t=getString(act);
781 	  	else t=getName(act);
782 	  	puts(t);
783 	  	free(t);
784 	  	break;
785 
786 #if 0
787 	  case 8: /* CONSTANT8 */
788 		if( wantstring )
789   		  printf ("'%s'", pool[act->p.Constant8]);
790 		else
791   		  printf ("%s", pool[act->p.Constant8]);
792 		break;
793 	  case 9: /* CONSTANT16 */
794 		if( wantstring )
795   		  printf ("'%s'", pool[act->p.Constant16]);
796 		else
797   		  printf ("%s", pool[act->p.Constant16]);
798 		break;
799 #endif
800 	case 12:
801 	case 11: /* INCREMENTED or DECREMENTED VARIABLE */
802 	case PUSH_VARIABLE: /* VARIABLE */
803 		printf ("%s", act->p.String);
804 		break;
805 	default:
806 		printf ("  Unknown type: %d\n", act->Type);
807 	}
808 }
809 
810 static void
decompileGETURL(SWF_ACTION * act)811 decompileGETURL (SWF_ACTION *act)
812 {
813 	OUT_BEGIN(SWF_ACTIONGETURL);
814 
815 	INDENT
816 	println("getUrl('%s',%s);", sact->UrlString, sact->TargetString);
817 }
818 
819 static int
decompileGETURL2(SWF_ACTION * act)820 decompileGETURL2 (SWF_ACTION *act)
821 {
822 	struct SWF_ACTIONPUSHPARAM *a,*b;
823 	OUT_BEGIN(SWF_ACTIONGETURL2);
824 	INDENT
825 
826 	a = pop();
827 	b = pop();
828 
829 	if (sact->f.FlagBits.SendVarsMethod==3)
830 		puts("loadVariables(");
831 	else
832 	{
833 		if (sact->f.FlagBits.SendVarsMethod==2)
834 			puts("loadVariablesNum(");
835 		else
836 		{
837 			if (sact->f.FlagBits.SendVarsMethod==1)
838 				puts("loadMovie(");
839 			else
840 			{
841 				if (*getName(a)=='_')	// found a _level
842 					puts("loadMovieNum(");
843 				else
844 					puts("getURL(");
845 			}
846 		}
847 	}
848 	decompilePUSHPARAM (b, 1);
849 	puts(",");
850 	decompilePUSHPARAM (a, 1);
851 	if  (sact->f.FlagBits.LoadVariableFlag)
852 		puts(",'GET'");
853 	if (sact->f.FlagBits.LoadTargetFlag)
854 		puts(",'POST'");
855 	println(");");
856 	return 0;
857 }
858 
OpCode(SWF_ACTION * actions,int n,int maxn)859 static inline int OpCode(SWF_ACTION *actions, int n, int maxn)
860 {
861 	if(!n || n >= maxn)
862 	{
863 #if DEBUG
864 		SWF_warn("OpCode: want %i, max %i\n", n, maxn);
865 #endif
866 		return -999;
867 	}
868 	return actions[n].SWF_ACTIONRECORD.ActionCode;
869 }
870 
871 static int
isStoreOp(int n,SWF_ACTION * actions,int maxn)872 isStoreOp(int n, SWF_ACTION *actions,int maxn)
873 {
874 	switch(OpCode(actions, n, maxn))
875 	{
876 	case SWFACTION_STOREREGISTER:
877 	case SWFACTION_SETVARIABLE:
878 	case SWFACTION_SETMEMBER:
879 	case SWFACTION_CASTOP:
880 		return 1;
881 	default:
882 		return 0;
883 	}
884 }
885 
886 static int
decompileGOTOFRAME(int n,SWF_ACTION * actions,int maxn,int islabel)887 decompileGOTOFRAME(int n, SWF_ACTION *actions,int maxn,int islabel)
888 {
889 	int i=0;
890 	struct SWF_ACTIONGOTOLABEL *sactv2;
891 	OUT_BEGIN2(SWF_ACTIONGOTOFRAME);
892 	sactv2 = (struct SWF_ACTIONGOTOLABEL*)sact;
893 	INDENT
894 	if (OpCode(actions, n+1, maxn) == SWFACTION_PLAY)
895 	{
896 		i=1;
897 		puts("gotoAndPlay(");
898 	}
899 	else
900 	{
901 		if (OpCode(actions, n+1, maxn) == SWFACTION_STOP)
902 			i=1;
903 		puts("gotoAndStop(");
904 	}
905 
906 	if (islabel)
907 		println("'%s');", sactv2->FrameLabel);
908 	else
909 		println("%d);", sact->Frame+1); /* GOTOFRAME arg is 0-based */
910 	return i;
911 }
912 
913 static int
decompileGOTOFRAME2(int n,SWF_ACTION * actions,int maxn)914 decompileGOTOFRAME2(int n, SWF_ACTION *actions, int maxn)
915 {
916 	int i=0;
917 	OUT_BEGIN2(SWF_ACTIONGOTOFRAME2);
918 	INDENT
919 	if (n+1 < maxn)
920 	{
921 		if (OpCode(actions, n+1, maxn) == SWFACTION_PLAY ||
922 		    OpCode(actions, n+1, maxn) == SWFACTION_STOP)
923 			i=1;
924 		if (OpCode(actions, n+1, maxn) == SWFACTION_PLAY)
925 			puts("gotoAndPlay(");
926 		else
927 		{
928 			if (OpCode(actions, n+1, maxn) == SWFACTION_STOP)
929 				puts("gotoAndStop(");
930 			else
931 			{
932 				if (sact->f.FlagBits.PlayFlag)
933 					puts("gotoAndPlay(");
934 				else
935 					puts("gotoAndStop(");
936 			}
937 		}
938 	}
939 	else
940 	{
941 		if (sact->f.FlagBits.PlayFlag)
942 			puts("gotoAndPlay(");
943 		else
944 			puts("gotoAndStop(");
945 	}
946 	decompilePUSHPARAM(pop(),0);
947 	println(");");
948 	return i;
949 }
950 
951 
precedence(int op1,int op2)952 static int precedence(int op1,int op2)
953 {
954 	static unsigned char ops[]= { 		// array of opcodes w rising precedence
955 //	SWFACTION_SETVARIABLE,		// TAKE CARE: array is incomplete
956 //	SWFACTION_TRACE,
957 	// missing ops are considered with low precedence
958 		SWFACTION_LOGICALOR,
959 		SWFACTION_LOGICALAND,
960 		SWFACTION_BITWISEOR,
961 		SWFACTION_BITWISEXOR,
962 		SWFACTION_BITWISEAND,
963 		SWFACTION_STRICTEQUALS,
964 		SWFACTION_EQUALS2,
965 		SWFACTION_EQUAL,
966 		SWFACTION_GREATER,
967 		SWFACTION_LESSTHAN,
968 		SWFACTION_LESS2,
969 		SWFACTION_SHIFTRIGHT,
970 		SWFACTION_SHIFTRIGHT2,
971 		SWFACTION_SHIFTLEFT,
972 		SWFACTION_ADD,
973 		SWFACTION_ADD2,
974 		SWFACTION_SUBTRACT,
975 		SWFACTION_MODULO,
976 		SWFACTION_MULTIPLY,
977 		SWFACTION_DIVIDE,
978 		SWFACTION_LOGICALNOT,
979 		SWFACTION_PUSH			// FIXME: need more analysis on code after PUSH
980 	};
981 	unsigned char* f=memchr(ops,op1,sizeof(ops));
982 	unsigned char* s=memchr(ops,op2,sizeof(ops));
983 #ifdef DEBUG
984 	printf("1op=%d 2op=%d  result=%d\n",op1,op2,f>s);
985 	if (!f) printf("opcode=%d NOT in precedence list\n",op1);
986 	if (!s) printf("opcode=%d NOT in precedence list\n",op2);
987 #endif
988 	return f>s;
989 }
990 
991 #ifdef DECOMP_SWITCH
992 static int
check_switch(int firstcode)993 check_switch(int firstcode)
994 {
995 	return (firstcode == SWFACTION_PUSH || firstcode == SWFACTION_JUMP);
996 }
997 #endif
998 
999 
1000 static int
decompileArithmeticOp(int n,SWF_ACTION * actions,int maxn)1001 decompileArithmeticOp(int n, SWF_ACTION *actions, int maxn)
1002 {
1003 	struct SWF_ACTIONPUSHPARAM *left, *right;
1004 	int op_l = OpCode(actions, n, maxn);
1005 	int op_r = OpCode(actions, n+1, maxn);
1006 	right=pop();
1007 	left=pop();
1008 	switch(OpCode(actions, n, maxn))
1009 	{
1010 	/*
1011 	case SWFACTION_GETMEMBER:
1012 		decompilePUSHPARAM(peek(),0);
1013 		break;
1014 	*/
1015 	case SWFACTION_INSTANCEOF:
1016 		if (precedence(op_l, op_r))
1017 			push(newVar3(getString(left)," instanceof ",getString(right)));
1018 		else
1019 			push(newVar_N("(",getString(left)," instanceof ",getString(right),0,")"));
1020 		break;
1021 	case SWFACTION_ADD:
1022 	case SWFACTION_ADD2:
1023 		if (precedence(op_l, op_r))
1024 			push(newVar3(getString(left),"+",getString(right)));
1025 		else
1026 			push(newVar_N("(",getString(left),"+",getString(right),0,")"));
1027 		break;
1028 	case SWFACTION_SUBTRACT:
1029 		if (precedence(op_l, op_r))
1030 			push(newVar3(getString(left),"-",getString(right)));
1031 		else
1032 			push(newVar_N("(",getString(left),"-",getString(right),0,")"));
1033 		break;
1034 	case SWFACTION_MULTIPLY:
1035 		if (precedence(op_l, op_r))
1036 			push(newVar3(getString(left),"*",getString(right)));
1037 		else
1038 			push(newVar_N("(",getString(left),"*",getString(right),0,")"));
1039 		break;
1040 	case SWFACTION_DIVIDE:
1041 		if (precedence(op_l, op_r))
1042 			push(newVar3(getString(left),"/",getString(right)));
1043 		else
1044 			push(newVar_N("(",getString(left),"/",getString(right),0,")"));
1045 		break;
1046 	case SWFACTION_MODULO:
1047 		if (precedence(op_l, op_r))
1048 			push(newVar3(getString(left),"%",getString(right)));
1049 		else
1050 			push(newVar_N("(",getString(left),"%",getString(right),0,")"));
1051 		break;
1052 	case SWFACTION_SHIFTLEFT:
1053 		if (precedence(op_l, op_r))
1054 			push(newVar3(getString(left),"<<",getString(right)));
1055 		else
1056 			push(newVar_N("(",getString(left),"<<",getString(right),0,")"));
1057 		break;
1058 	case SWFACTION_SHIFTRIGHT:
1059 		if (precedence(op_l, op_r))
1060 			push(newVar3(getString(left),">>",getString(right)));
1061 		else
1062 			push(newVar_N("(",getString(left),">>",getString(right),0,")"));
1063 		break;
1064 	case SWFACTION_SHIFTRIGHT2:
1065 		if (precedence(op_l, op_r))
1066 			push(newVar3(getString(left),">>>",getString(right)));
1067 		else
1068 			push(newVar_N("(",getString(left),">>>",getString(right),0,")"));
1069 		break;
1070 	case SWFACTION_LOGICALAND:
1071 		if (precedence(op_l, op_r))
1072 			push(newVar3(getString(left),"&&",getString(right)));
1073 		else
1074 			push(newVar_N("(",getString(left),"&&",getString(right),0,")"));
1075 		break;
1076 	case SWFACTION_LOGICALOR:
1077 		if (precedence(op_l, op_r))
1078 			push(newVar3(getString(left),"||",getString(right)));
1079 		else
1080 			push(newVar_N("(",getString(left),"||",getString(right),0,")"));
1081 		break;
1082 	case SWFACTION_BITWISEAND:
1083 		if (precedence(op_l, op_r))
1084 			push(newVar3(getString(left),"&",getString(right)));
1085 		else
1086 			push(newVar_N("(",getString(left),"&",getString(right),0,")"));
1087 		break;
1088 	case SWFACTION_BITWISEOR:
1089 		if (precedence(op_l, op_r))
1090 			push(newVar3(getString(left),"|",getString(right)));
1091 		else
1092 			push(newVar_N("(",getString(left),"|",getString(right),0,")"));
1093 		break;
1094 	case SWFACTION_BITWISEXOR:
1095 		if (precedence(op_l, op_r))
1096 			push(newVar3(getString(left),"^",getString(right)));
1097 		else
1098 			push(newVar_N("(",getString(left),"^",getString(right),0,")"));
1099 		break;
1100 	case SWFACTION_EQUALS2:	/* including negation */
1101 	case SWFACTION_EQUAL:
1102 		if( OpCode(actions, n+1, maxn) == SWFACTION_LOGICALNOT &&
1103 		    OpCode(actions, n+2, maxn) != SWFACTION_IF)
1104 		{
1105 			op_r = OpCode(actions, n+1, maxn);
1106 			if (precedence(op_l, op_r))
1107 				push(newVar3(getString(left),"!=",getString(right)));
1108 			else
1109 				push(newVar_N("(",getString(left),"!=",getString(right),0,")"));
1110 			return 1; /* due negation op */
1111 		}
1112 		if (precedence(op_l, op_r))
1113 			push(newVar3(getString(left),"==",getString(right)));
1114 		else
1115 			push(newVar_N("(",getString(left),"==",getString(right),0,")"));
1116 		break;
1117 	case SWFACTION_LESS2:
1118 		if( OpCode(actions, n+1, maxn)  == SWFACTION_LOGICALNOT &&
1119 		    OpCode(actions, n+2, maxn) != SWFACTION_IF )
1120 		{
1121 			op_r = OpCode(actions, n+2, maxn);
1122 			if (precedence(op_l, op_r))
1123 				push(newVar3(getString(left),">=",getString(right)));
1124 			else
1125 				push(newVar_N("(",getString(left),">=",getString(right),0,")"));
1126 			return 1; /* due negation op */
1127 		}
1128 		if (precedence(op_l, op_r))
1129 			push(newVar3(getString(left),"<",getString(right)));
1130 		else
1131 			push(newVar_N("(",getString(left),"<",getString(right),0,")"));
1132 		break;
1133 	case SWFACTION_GREATER:
1134 		if (precedence(op_l, op_r))
1135 			push(newVar3(getString(left),">",getString(right)));
1136 		else
1137 			push(newVar_N("(",getString(left),">",getString(right),0,")"));
1138 		break;
1139 	case SWFACTION_LESSTHAN:
1140 		if (precedence(op_l, op_r))
1141 			push(newVar3(getString(left),"<",getString(right)));
1142 		else
1143 			push(newVar_N("(",getString(left),"<",getString(right),0,")"));
1144 		break;
1145 	case SWFACTION_STRINGEQ:
1146 		if (precedence(op_l, op_r))
1147 			push(newVar3(getString(left),"==",getString(right)));
1148 		else
1149 			push(newVar_N("(",getString(left),"==",getString(right),0,")"));
1150 		break;
1151 	case SWFACTION_STRINGCOMPARE:
1152 		puts("STRINGCOMPARE");
1153 		break;
1154 	case SWFACTION_STRICTEQUALS:
1155 #ifdef DECOMP_SWITCH
1156 		if  (OpCode(actions, n, maxn) == SWFACTION_IF)
1157 		{
1158 			int code = actions[n+1].SWF_ACTIONIF.Actions[0].SWF_ACTIONRECORD.ActionCode;
1159 			if(check_switch(code))
1160 			{
1161 				push(right);	// keep left and right side separated
1162 				push(left);	// because it seems we have found a switch(){} and
1163 				break;	// let decompileIF() once more do all the dirty work
1164 			}
1165 		}
1166 #endif
1167 		if( OpCode(actions, n+1, maxn) == SWFACTION_LOGICALNOT &&
1168 		    OpCode(actions, n+2, maxn) != SWFACTION_IF )
1169 		{
1170 			op_r = OpCode(actions, n+2, maxn);
1171 			if (precedence(op_l, op_r))
1172 				push(newVar3(getString(left),"!==",getString(right)));
1173 			else
1174 				push(newVar_N("(",getString(left),"!==",getString(right),0,")"));
1175 			return 1; /* due negation op */
1176 		} else {
1177 			if (precedence(op_l, op_r))
1178 				push(newVar3(getString(left),"===",getString(right)));
1179 			else
1180 				push(newVar_N("(",getString(left),"===",getString(right),0,")"));
1181 			break;
1182 		}
1183 	default:
1184 		printf("Unhandled Arithmetic/Logic OP %x\n",
1185 			actions[n].SWF_ACTIONRECORD.ActionCode);
1186 	}
1187 	return 0;
1188 }
1189 
1190 static int
isLogicalOp(int n,SWF_ACTION * actions,int maxn)1191 isLogicalOp(int n, SWF_ACTION *actions, int maxn)
1192 {
1193 	switch(OpCode(actions, n, maxn))
1194 	{
1195 	case SWFACTION_LESSTHAN:
1196 	case SWFACTION_LOGICALAND:
1197 	case SWFACTION_LOGICALOR:
1198 	case SWFACTION_LOGICALNOT:
1199 	case SWFACTION_STRINGEQ:
1200 	case SWFACTION_STRINGCOMPARE:
1201 	case SWFACTION_LESS2:
1202 	case SWFACTION_EQUALS2:
1203 	case SWFACTION_EQUAL:
1204 	case SWFACTION_BITWISEAND:
1205 	case SWFACTION_BITWISEOR:
1206 	case SWFACTION_BITWISEXOR:
1207 	case SWFACTION_STRICTEQUALS:
1208 	case SWFACTION_GREATER:
1209 	/*
1210 	case SWFACTION_GETMEMBER:
1211 	*/
1212 		return 1;
1213 	default:
1214 		return 0;
1215 	}
1216 }
1217 
1218 static int
isLogicalOp2(int n,SWF_ACTION * actions,int maxn)1219 isLogicalOp2(int n, SWF_ACTION *actions,int maxn)
1220 {
1221 	switch(actions[n].SWF_ACTIONRECORD.ActionCode)
1222 	{
1223 	case SWFACTION_LOGICALNOT:
1224 	case SWFACTION_PUSHDUP:
1225 	case SWFACTION_IF:
1226 		return 1;
1227 	default:
1228 		return 0;
1229 	}
1230 }
1231 
1232 static int
stackVal(int n,SWF_ACTION * actions)1233 stackVal(int n, SWF_ACTION *actions)
1234 {
1235 	if (!n)
1236 		return 0;
1237 
1238 	switch((actions[n-1]).SWF_ACTIONRECORD.ActionCode)
1239 	{
1240 	case SWFACTION_LOGICALNOT:
1241 	case SWFACTION_DECREMENT:
1242 	case SWFACTION_INCREMENT:
1243 	case SWFACTION_RANDOMNUMBER:
1244 	case SWFACTION_TOSTRING:
1245 	case SWFACTION_TONUMBER:
1246 	case SWFACTION_ORD:
1247 	case SWFACTION_CHR:
1248 	case SWFACTION_MBORD:
1249 	case SWFACTION_MBCHR:
1250 	case SWFACTION_INT:
1251 	case SWFACTION_GETVARIABLE:
1252 	case SWFACTION_SUBSTRING:
1253 	case SWFACTION_MBSUBSTRING:
1254 	case SWFACTION_GETMEMBER:
1255 	case SWFACTION_ADD:
1256 	case SWFACTION_ADD2:
1257 	case SWFACTION_SUBTRACT:
1258 	case SWFACTION_MULTIPLY:
1259 	case SWFACTION_DIVIDE:
1260 	case SWFACTION_MODULO:
1261 	case SWFACTION_BITWISEAND:
1262 	case SWFACTION_BITWISEOR:
1263 	case SWFACTION_BITWISEXOR:
1264 	case SWFACTION_LESSTHAN:
1265 	case SWFACTION_LOGICALAND:
1266 	case SWFACTION_LOGICALOR:
1267 	case SWFACTION_STRINGEQ:
1268 	case SWFACTION_STRINGCOMPARE:
1269 	case SWFACTION_LESS2:
1270 	case SWFACTION_EQUALS2:
1271 	case SWFACTION_EQUAL:
1272 	case SWFACTION_STRICTEQUALS:
1273 	case SWFACTION_GREATER:
1274 	case SWFACTION_STRINGGREATER:
1275 	case SWFACTION_STRINGCONCAT:
1276 	case SWFACTION_SHIFTLEFT:
1277 	case SWFACTION_SHIFTRIGHT:
1278 	case SWFACTION_SHIFTRIGHT2:
1279 	case SWFACTION_INSTANCEOF:
1280 	case SWFACTION_CALLMETHOD:
1281 	case SWFACTION_CALLFUNCTION:
1282 	case SWFACTION_GETTIME:
1283 	case SWFACTION_GETPROPERTY:
1284 	case SWFACTION_PUSH:
1285 	case SWFACTION_DELETE:
1286 	case SWFACTION_DELETE2:
1287 	case SWFACTION_MBLENGTH:
1288 	case SWFACTION_STRINGLENGTH:
1289 	case SWFACTION_CASTOP:
1290 	case SWFACTION_TYPEOF:
1291 	case SWFACTION_PUSHDUP:
1292 		return 1;
1293 	default:
1294 	return 0;
1295 	}
1296 }
1297 
1298 static int
decompileLogicalNot(int n,SWF_ACTION * actions,int maxn)1299 decompileLogicalNot(int n, SWF_ACTION *actions, int maxn)
1300 {
1301 #ifdef STATEMENT_CLASS
1302 	if(OpCode(actions, n-1, maxn) == SWFACTION_GETVARIABLE &&
1303 	   OpCode(actions, n+1, maxn) == SWFACTION_LOGICALNOT &&
1304 	   OpCode(actions, n+2, maxn) == SWFACTION_IF )
1305 	{
1306 		/* It's a class statement  -- skip over both NOTs */
1307 		return 1;
1308 	}
1309 #endif
1310 	if(OpCode(actions, n+1, maxn) != SWFACTION_IF )
1311 		push(newVar2("!",getString(pop())));
1312 	return 0;
1313 }
1314 
1315 static void
decompilePUSH(SWF_ACTION * act)1316 decompilePUSH (SWF_ACTION *act)
1317 {
1318 	int i;
1319 	OUT_BEGIN(SWF_ACTIONPUSH);
1320 
1321 	SanityCheck(SWF_PUSH,
1322 		act->SWF_ACTIONRECORD.ActionCode == SWFACTION_PUSH,
1323 		"not a PUSH")
1324 
1325 	for(i=0;i<sact->NumParam;i++)
1326 		push(&(sact->Params[i]));
1327 }
1328 
1329 static void
decompilePUSHDUP(SWF_ACTION * act)1330 decompilePUSHDUP (SWF_ACTION *act)
1331 {
1332 	SanityCheck(SWF_PUSHDUP,
1333 		act->SWF_ACTIONRECORD.ActionCode == SWFACTION_PUSHDUP,
1334 		"not a PUSHDUP")
1335 	pushdup();
1336 }
1337 
1338 static void
decompileSTACKSWAP(SWF_ACTION * act)1339 decompileSTACKSWAP (SWF_ACTION *act)
1340 {
1341 	SanityCheck(SWF_STACKSWAP,
1342 		act->SWF_ACTIONRECORD.ActionCode == SWFACTION_STACKSWAP,
1343 		"not a STACKSWAP")
1344 	stackswap();
1345 }
1346 
1347 static int
decompileSETPROPERTY(int n,SWF_ACTION * actions,int maxn)1348 decompileSETPROPERTY(int n, SWF_ACTION *actions,int maxn)
1349 {
1350 	struct SWF_ACTIONPUSHPARAM *val, *idx, *obj;
1351 
1352 	INDENT
1353 	val = pop();
1354 	idx = pop();
1355 	obj = pop();
1356 #ifdef DEBUG
1357 	printf("*setProp* objName %s (type=%d) Prop (type=%d) =%x\n",
1358 	       getName(obj), obj->Type, idx->Type,getInt(idx));
1359 #endif
1360 	if (obj->Type == PUSH_VARIABLE)
1361 		puts("eval(");
1362 
1363 	decompilePUSHPARAM(obj,0);
1364 	if (obj->Type == PUSH_VARIABLE)
1365 		puts(")");
1366 
1367 	puts(".");
1368 	puts(getProperty(getInt(idx)));
1369 	printf(" = " );
1370 	decompilePUSHPARAM(val,0);
1371 	println(";");
1372 	return 0;
1373 }
1374 
1375 static int
decompileGETPROPERTY(int n,SWF_ACTION * actions,int maxn)1376 decompileGETPROPERTY(int n, SWF_ACTION *actions,int maxn)
1377 {
1378 	struct SWF_ACTIONPUSHPARAM *idx, *obj;
1379 
1380 	INDENT
1381 	idx = pop();
1382 	obj = pop();
1383 #ifdef DEBUG
1384 	printf("*GETProp* objName %s (type=%d) Prop (type=%d) =%x\n",
1385 	       getName(obj), obj->Type, idx->Type,getInt(idx));
1386 #endif
1387 	if (obj->Type == PUSH_VARIABLE)
1388 		push( newVar5("eval(",getName(obj),".",getProperty(getInt(idx)),")"));
1389 	else
1390 		push( newVar3( getName(obj),".",getProperty(getInt(idx))));
1391 	return 0;
1392 }
1393 
1394 static int
decompileTRACE(int n,SWF_ACTION * actions,int maxn)1395 decompileTRACE(int n, SWF_ACTION *actions, int maxn)
1396 {
1397 	INDENT
1398 	puts("trace(");
1399 	decompilePUSHPARAM(pop(),1);
1400 	println(");");
1401 	return 0;
1402 }
1403 
1404 static int
decompileCALLFRAME(int n,SWF_ACTION * actions,int maxn)1405 decompileCALLFRAME(int n, SWF_ACTION *actions, int maxn)
1406 {
1407 	INDENT
1408 	puts("callFrame(");
1409 	decompilePUSHPARAM(pop(),1);
1410 	println(");");
1411 	return 0;
1412 }
1413 
1414 static int
decompileGETTIME(int n,SWF_ACTION * actions,int maxn)1415 decompileGETTIME(int n, SWF_ACTION *actions, int maxn)
1416 {
1417 	if (OpCode(actions, n+1, maxn) == SWFACTION_POP)
1418 	{
1419 		INDENT
1420 		println("getTimer();");
1421 		return 1;
1422 	}
1423 	else
1424 	{
1425 		push(newVar("getTimer()"));
1426 		return 0;
1427 	}
1428 }
1429 
1430 static int
decompileINCR_DECR(int n,SWF_ACTION * actions,int maxn,int is_incr)1431 decompileINCR_DECR(int n, SWF_ACTION *actions, int maxn, int is_incr)
1432 {
1433 	int is_postop;
1434 	struct SWF_ACTIONPUSHPARAM *var=pop();
1435 	char *dblop=is_incr ? "++":"--";
1436 
1437 	if((OpCode(actions, n, maxn) == SWFACTION_PUSHDUP
1438 	     || OpCode(actions, n+1, maxn) == SWFACTION_PUSHDUP
1439 	     || OpCode(actions, n+1, maxn) == SWFACTION_SETVARIABLE)
1440 	     || ( OpCode(actions, n-1, maxn) == SWFACTION_GETVARIABLE
1441 	          &&  OpCode(actions, n+1, maxn) == SWFACTION_STOREREGISTER
1442 	          &&  OpCode(actions, n+1, maxn) == SWFACTION_SETVARIABLE))
1443 	{
1444 		is_postop=(OpCode(actions, n-1, maxn) == SWFACTION_PUSHDUP)?1:0;
1445 		if (is_postop)
1446 			var = newVar2(getString(var),dblop);
1447 		else
1448 			var = newVar2(dblop,getString(var));
1449 		if (OpCode(actions, n+1, maxn) == SWFACTION_SETVARIABLE)
1450 		{
1451 			var->Type=11;	/* later trigger printing variable inc/dec */
1452 		}
1453 		else
1454 		{
1455 			var->Type=12;	/* later be quiet, see decompileSETVARIABLE() */
1456 			if (is_postop)
1457 			{
1458 				pop();
1459 				push(var);	/* will duplicate stacktop */
1460 			}
1461 		}
1462 		push(var);
1463 	}
1464 	else
1465 	{
1466 		if((OpCode(actions, n-1, maxn) == SWFACTION_GETMEMBER &&
1467 		    OpCode(actions, n+1, maxn) == SWFACTION_STOREREGISTER &&
1468 		    OpCode(actions, n+2, maxn) == SWFACTION_SETMEMBER ) ||
1469 		   (OpCode(actions, n-1, maxn) == SWFACTION_STOREREGISTER &&
1470 	    	    OpCode(actions, n+1, maxn) == SWFACTION_SETMEMBER &&
1471 		    OpCode(actions, n+2, maxn) == SWFACTION_PUSH ) ||
1472 		   (OpCode(actions, n-1, maxn) == SWFACTION_PUSH &&
1473 		    OpCode(actions, n+1, maxn) == SWFACTION_SETMEMBER)  ||
1474 		   (OpCode(actions, n-3, maxn) == SWFACTION_GETMEMBER &&
1475 		    OpCode(actions, n-2, maxn) == SWFACTION_PUSH &&
1476 		    OpCode(actions, n-1, maxn) == SWFACTION_GETMEMBER &&
1477 		    OpCode(actions, n+1, maxn) == SWFACTION_SETMEMBER &&
1478 	    	((struct SWF_ACTIONPUSH *)&actions[n-2].SWF_ACTIONRECORD)->NumParam >= 4
1479 	    		/* 4: a pair of get/set - FIXME: add more analysis about stack here */))
1480 		{		// incr/decr object variables with side effects
1481 			is_postop= (OpCode(actions, n+1, maxn) == SWFACTION_SETMEMBER)?1:0;
1482 			if (is_postop)
1483 				var = newVar2(getString(var),dblop);
1484 			else
1485 				var = newVar2(dblop,getString(var));
1486 			if (is_postop && OpCode(actions, n-1, maxn) == SWFACTION_PUSH)
1487 				pop();
1488 			if(OpCode(actions, n+1, maxn) == SWFACTION_GETMEMBER)
1489 				pop();
1490 
1491 			pop();
1492 			pop();
1493 			var->Type=12;	// to be quiet later in ...SETMEMBER()
1494 			regs[0]=var;	// FIXME: r0 perhaps a ming special
1495 			push(var);
1496 			push(var);
1497 			push(var);
1498 
1499 			if (is_postop && OpCode(actions, n-1, maxn) == SWFACTION_PUSH )
1500 				push(var);
1501 			if (is_postop && OpCode(actions, n-1, maxn) == SWFACTION_GETMEMBER )
1502 				push(var);
1503 		}
1504 		else
1505 		{
1506 			if(OpCode(actions, n-1, maxn) == SWFACTION_PUSH &&
1507 			   OpCode(actions, n+1, maxn) == SWFACTION_STOREREGISTER &&
1508 			   regs[actions[n+1].SWF_ACTIONSTOREREGISTER.Register]->Type == PUSH_VARIABLE)
1509 			{
1510 				var = newVar2(dblop,getString(var));
1511 				if ((OpCode(actions, n+2, maxn) == SWFACTION_POP
1512 				     && actions[n-1].SWF_ACTIONPUSH.NumParam==1)
1513 				    || OpCode(actions, n+3, maxn) == SWFACTION_POP)
1514 				{
1515 					var->Type=11;	// later print inc/dec
1516 				}
1517 				else
1518 				{
1519 					var->Type=12;	// later be quiet in ..STOREREGISTER()
1520 					if (actions[n-1].SWF_ACTIONPUSH.NumParam>1)
1521 					{
1522 						pop();
1523 						push(var);
1524 					}
1525 				}
1526 				push(var);
1527 			}
1528 			else		// fallback to old incr/decr code
1529 			{		// FIXME: this is bad designed for handling side effect code
1530 				INDENT	//        like post-incrementing a function argument etc.
1531 				decompilePUSHPARAM(var,0);
1532 				puts(dblop);
1533 				println(";");
1534 				push(var);
1535 			}
1536 		}
1537 	}
1538 	return 0;
1539 }
1540 
1541 static int
decompileSTOREREGISTER(int n,SWF_ACTION * actions,int maxn)1542 decompileSTOREREGISTER(int n, SWF_ACTION *actions, int maxn)
1543 {
1544 	struct SWF_ACTIONPUSHPARAM *data;
1545 	OUT_BEGIN2(SWF_ACTIONSTOREREGISTER);
1546 	data=peek();
1547 
1548 	if (!regs[sact->Register] || sact->Register==0 )	// ===internal===
1549 	{
1550 		regs[sact->Register] = data;
1551 	}
1552 	else						// ===user visible level===
1553 	{
1554 		if ( regs[sact->Register]->Type == PUSH_VARIABLE) // V7: a named function parameter in register
1555 		{						// V7: a local var in register
1556 			if (data->Type==12)
1557 				data->Type = PUSH_VARIABLE;			// do nothing, but only once
1558 			else
1559 			{
1560 				char *l=getName(regs[sact->Register]);
1561 				char *r=getName(data);
1562 				if (strcmp(l,r))
1563 				{
1564 					INDENT
1565 					if (data->Type==11)
1566 					{
1567 						println("%s;", r);
1568 					}
1569 					else
1570 					{
1571 						printf("%s = ",l);
1572 						decompilePUSHPARAM(data,1);
1573 						println(";");
1574 					}
1575 				}
1576 			}
1577 		}
1578 	}
1579 	return 0;
1580 }
1581 
1582 static int
decompileNEWOBJECT(int n,SWF_ACTION * actions,int maxn)1583 decompileNEWOBJECT(int n, SWF_ACTION *actions, int maxn)
1584 {
1585 	struct SWF_ACTIONPUSHPARAM *obj, *nparam;
1586 	obj = pop();
1587 	nparam=pop();
1588 	push(newVar_N("new ","",getName(obj),"(", nparam->p.Integer,")"));
1589 	return 0;
1590 }
1591 
1592 static int
decompileNEWMETHOD(int n,SWF_ACTION * actions,int maxn)1593 decompileNEWMETHOD(int n, SWF_ACTION *actions, int maxn)
1594 {
1595 	char *t;
1596 	struct SWF_ACTIONPUSHPARAM *meth, *nparam, *obj;
1597 	meth = pop();
1598 	obj = pop();
1599 	nparam=pop();
1600 
1601 	t=malloc(strlen( getName(obj) ) +2);
1602 	strcpy(t,getName(obj));
1603 	strcat(t,".");
1604 
1605 	push(newVar_N("new ",t,getName(meth),"(", nparam->p.Integer,")"));
1606 	free (t);
1607 	return 0;
1608 }
1609 
1610 
1611 static int
decompileGETMEMBER(int n,SWF_ACTION * actions,int maxn)1612 decompileGETMEMBER(int n, SWF_ACTION *actions, int maxn)
1613 {
1614 	struct SWF_ACTIONPUSHPARAM *obj, *mem, *var;
1615 	char *vname, *varname,*memname;
1616 	int len;
1617 
1618 	mem=pop();
1619 	var=pop();
1620 	varname=getName(var);
1621 	memname=getName(mem);
1622 #ifdef DEBUG
1623 	printf("*getMember* varName %s (type=%d)  memName=%s (type=%d)\n",
1624 	       varname,var->Type, memname,mem->Type);
1625 #endif
1626 	len = strlen(varname)+strlen(memname);
1627 	if (mem->Type == PUSH_INT || mem->Type == PUSH_DOUBLE || mem->Type == PUSH_VARIABLE
1628 	    || mem->Type == PUSH_REGISTER || mem->Type == 12 )
1629 	{
1630 		vname = malloc(len+3);
1631 		strcpy(vname,varname);
1632 		strcat(vname,"[");
1633 		strcat(vname,memname);
1634 		strcat(vname,"]");
1635 	}
1636 	else
1637 	{
1638 		vname = malloc(len+2);
1639 		strcpy(vname,varname);
1640 		strcat(vname,".");
1641 		strcat(vname,memname);
1642 	}
1643 	obj = newVar(vname);
1644 	pushvar(obj);
1645 
1646 	return 0;
1647 }
1648 
1649 
1650 static int
decompileSETMEMBER(int n,SWF_ACTION * actions,int maxn)1651 decompileSETMEMBER(int n, SWF_ACTION *actions, int maxn)
1652 {
1653 	struct SWF_ACTIONPUSHPARAM *val, *var, *obj;
1654 	val = pop();
1655 	var = pop();
1656 	obj = pop();
1657 
1658 #ifdef DEBUG
1659 	printf("*SETMember* varName %s (type=%d)  objName=%s (type=%d)\n",getName(var),var->Type, getName(obj),obj->Type);
1660 #endif
1661 	if (obj->Type == 12)				/* do nothing: inline inc/dec using side effect */
1662 	{
1663 		obj->Type = PUSH_VARIABLE;		/* ...but only once */
1664 		return 0;
1665 	}
1666 	INDENT
1667 	if (obj->Type == 11)				/* simply output variable and inc/dec op */
1668 	{
1669 		decompilePUSHPARAM(obj,0);
1670 		println(";");
1671 		return 0;
1672 	}
1673 
1674 	decompilePUSHPARAM(obj,0);
1675 	if (var->Type == PUSH_INT || var->Type == PUSH_DOUBLE || var->Type == PUSH_VARIABLE
1676 	    || var->Type == PUSH_REGISTER || var->Type == 12 )
1677 	{
1678 		puts("[");
1679 	}
1680 	else
1681 	{
1682 		puts(".");
1683 		if (OpCode(actions, n-1, maxn) == SWFACTION_STOREREGISTER)
1684 		{
1685 			struct SWF_ACTIONSTOREREGISTER *sactv2 = (struct SWF_ACTIONSTOREREGISTER*)&actions[n-1];
1686 			if (sactv2->Register==0)
1687 				regs[0]=newVar3(getName(obj),".",getName(var));		// easter 07: some sugar for mtc et al.
1688 		}
1689 	}
1690 	decompilePUSHPARAM(var,0);
1691 	if (var->Type == PUSH_INT || var->Type == PUSH_DOUBLE || var->Type == PUSH_VARIABLE
1692 		|| var->Type == PUSH_REGISTER || var->Type == 12 )
1693 	{
1694 		puts("]");
1695 	}
1696 	printf(" = " );
1697 
1698 
1699 	if ( OpCode(actions, n-1, maxn) == SWFACTION_STOREREGISTER ) {
1700 		struct SWF_ACTIONSTOREREGISTER *sr =
1701 			(struct SWF_ACTIONSTOREREGISTER*)&actions[n-1];
1702 		printf("R%d", sr->Register);
1703 	}
1704 	else if (val->Type != PUSH_VARIABLE) {
1705 		/* later it will be a switch{} */
1706 		decompilePUSHPARAM(val,1);
1707 	}
1708 	else {
1709 		decompilePUSHPARAM(val,0);
1710 	}
1711 	println(";");
1712 	return 0;
1713 }
1714 
1715 static int
decompileGETVARIABLE(int n,SWF_ACTION * actions,int maxn)1716 decompileGETVARIABLE(int n, SWF_ACTION *actions, int maxn)
1717 {
1718 	struct SWF_ACTIONPUSHPARAM *var;
1719 
1720 	var = pop();
1721 #ifdef DEBUG
1722 	printf("*GETVariable* varName %s (type=%d)\n",getName(var),var->Type);
1723 #endif
1724 	if (var->Type == PUSH_VARIABLE)
1725 		pushvar(newVar3("eval(",getName(var),")"));
1726 	else
1727 		pushvar(newVar(getName(var)));
1728 
1729 	return 0;
1730 }
1731 
1732 static int
decompileSETVARIABLE(int n,SWF_ACTION * actions,int maxn,int islocalvar)1733 decompileSETVARIABLE(int n, SWF_ACTION *actions,int maxn,int islocalvar)
1734 {
1735 	struct SWF_ACTIONPUSHPARAM *val, *var;
1736 
1737 	val = pop();
1738 	var = pop();
1739 	if (val->Type!=12)
1740 	{
1741 		INDENT
1742 	}
1743 #ifdef DEBUG
1744 	printf("*SETVariable* varName %s (type=%d)  valName=%s (type=%d)\n",
1745 	       getName(var),var->Type, getName(val),val->Type);
1746 #endif
1747 	if (val->Type!=12 && islocalvar)
1748 	{
1749 		puts("var ");
1750 	}
1751 	if (gIndent<0)	/* the ENUM workaround:  */
1752 	{			/* in "for (xx in yy) { }" we need xx, but nothing else */
1753 		puts(getName(var));
1754 		return 0;
1755 	}
1756 
1757 
1758 	switch (val->Type)
1759 	{
1760 	case 10:
1761 		puts(getName(var));		// Variable (NEVER as string)
1762 		printf(" = " );
1763 		decompilePUSHPARAM(val,0);
1764 		println(";");
1765 		break;
1766 	case 11:				/* simply output variable and inc/dec op */
1767 		puts(getName(val));
1768 		println(";");
1769 		break;
1770 	case 12:				/* do nothing: inline increment/decrement (using side effect only) */
1771 		val->Type = PUSH_VARIABLE;     		// but print next time  e.g. in y=++x;
1772 		break;
1773 	default:
1774 		puts(getName(var));
1775 		printf(" = " );
1776 		decompilePUSHPARAM(val,1);	// for certain types parameter 1 does not care
1777 		println(";");
1778 	}
1779 	return 0;
1780 }
1781 
1782 static int
decompileRETURN(int n,SWF_ACTION * actions,int maxn)1783 decompileRETURN(int n, SWF_ACTION *actions, int maxn)
1784 {
1785 	struct SWF_ACTIONPUSHPARAM *var=pop();
1786 	INDENT
1787 	printf("return ");
1788 	if (var->Type== PUSH_REGISTER && var->p.RegisterNumber==0)	/* REGISTER 0 used as helper variable */
1789 		puts(getName(regs[0]));
1790 	else
1791 		decompilePUSHPARAM(var,1);
1792 	println(";");
1793 	return 0;
1794 }
1795 
1796 static int
decompileJUMP(int n,SWF_ACTION * actions,int maxn)1797 decompileJUMP(int n, SWF_ACTION *actions, int maxn)
1798 {
1799 	int i=0,j=0;
1800 	int offSave;
1801 	struct SWF_ACTIONIF *sactif;
1802 	OUT_BEGIN2(SWF_ACTIONJUMP);
1803 	sactif=NULL;
1804 
1805 	if(isLogicalOp(n+1, actions, maxn) ||
1806 	   (OpCode(actions, n+1, maxn) == SWFACTION_PUSH && isLogicalOp(n+2, actions, maxn)))
1807 	{
1808 		/* Probably the start of a do {} while(), so skip it */
1809 		return 0;
1810 	}
1811 
1812 	/* Probably the end of a switch{}, so skip it */
1813 	if (OpCode(actions, n+1, maxn) == SWFACTION_POP)
1814 		return 1;
1815 
1816 	if (OpCode(actions, n+1, maxn) == SWFACTION_JUMP)
1817 	{
1818 		if (actions[n+1].SWF_ACTIONJUMP.BranchOffset==0)
1819 			return 1;
1820 	}
1821 
1822 	for(i=0; n + 1 + i < maxn && (actions[(n+1)+i].SWF_ACTIONRECORD.Offset < (actions[n+1].SWF_ACTIONRECORD.Offset+actions[n ].SWF_ACTIONJUMP.BranchOffset)); i++)
1823 	{
1824 #if 0
1825 		printf("/* for PART3 OP 0x%x */\n",actions[n+1+i].SWF_ACTIONRECORD.ActionCode);
1826 #endif
1827 		; // NOOP
1828 	}
1829 
1830 	if (i)
1831 	{
1832 		for (j=0; n+j+i<maxn; j++)
1833 		{
1834 #if 0
1835 			 printf("/* FOR part2 OP 0x%x */\n",actions[n+i+j].SWF_ACTIONRECORD.ActionCode)
1836 			// at least one should push on stack
1837 #endif
1838 
1839 			if (OpCode(actions, n+i+j, maxn) == SWFACTION_IF)
1840 			{
1841 				sactif = (struct SWF_ACTIONIF *)&(actions[n+i+j]);
1842 				/* chk whether last jump does lead us back to start of loop */
1843 				if (sactif->Actions[sactif->numActions-1].SWF_ACTIONRECORD.ActionCode==SWFACTION_JUMP
1844 				    && sactif->Actions[sactif->numActions-1].SWF_ACTIONJUMP.BranchOffset+
1845 				    sactif->Actions[sactif->numActions-1].SWF_ACTIONJUMP.Offset==
1846 				    actions[n].SWF_ACTIONRECORD.Offset )
1847 				{
1848 					break;
1849 				}
1850 				else
1851 					sactif=NULL;
1852 			}
1853 		}
1854 	}
1855 
1856 	if (sactif)
1857 	{
1858 		INDENT
1859 		puts("while(");
1860 		decompileActions(j-1, &actions[n+1+i], gIndent);
1861 		puts(getName(pop()));
1862 		println("){         /* original FOR loop rewritten to WHILE */");
1863 		offSave=offseoloop;
1864 		if (n+i+j+1<maxn)						// see part2 above
1865 			offseoloop=actions[n+i+j+1].SWF_ACTIONRECORD.Offset;
1866 		else
1867 			offseoloop=actions[n+i+j].SWF_ACTIONRECORD.Offset+5;
1868 		decompileActions(sactif->numActions-1, sactif->Actions,gIndent+1);
1869 		decompileActions(i, &actions[n+1], gIndent+1);
1870 		offseoloop=offSave;
1871 		INDENT
1872 		println("};");
1873 		return i+j;
1874 	}
1875 
1876 	if (sact->BranchOffset>0)
1877 	{
1878 		if ( stackVal(n,actions) == 1 && n+1==maxn)
1879 		{	// leaving block @last op with value on stack: a return x;
1880 			return decompileRETURN(n, actions,maxn);
1881 		}
1882 		if (n+2 < maxn && OpCode(actions, n+1, maxn) == SWFACTION_PUSH &&
1883 			actions[n+2].SWF_ACTIONRECORD.Offset == actions[n+1].SWF_ACTIONRECORD.Offset+sact->BranchOffset)
1884 		{
1885 			return 1; 	// jump to short to be a 'break': but an internal jump over a push
1886 		}			// to do: add some control flow analysis
1887 
1888 		INDENT
1889 
1890 		if (offseoloop==actions[n].SWF_ACTIONRECORD.Offset+sact->BranchOffset+5)
1891 			puts("break;" );
1892 		else
1893 			puts("return;" );
1894 
1895 		println("\t\t\t// offs_end_of_loop=%d  offs_jmp_dest=%d",
1896 		        offseoloop, actions[n].SWF_ACTIONRECORD.Offset+sact->BranchOffset+5);
1897 	}
1898 	else
1899 	{
1900 		if (sact->BranchOffset<0)
1901 		{
1902 			INDENT
1903 			println("continue;     /*------*/");
1904 		}
1905 	}
1906 	/* error("Unhandled JUMP"); */
1907 	return 0;
1908 }
1909 
1910 static int
decompileDEFINELOCAL2(int n,SWF_ACTION * actions,int maxn)1911 decompileDEFINELOCAL2(int n, SWF_ACTION *actions, int maxn)
1912 {
1913 	struct SWF_ACTIONPUSHPARAM *var;
1914 
1915 	INDENT
1916 	var = pop();
1917 	puts("var ");
1918 	puts(getName(var));
1919 	println(";");
1920 
1921 	return 0;
1922 }
1923 
1924 static int
decompileENUMERATE(int n,SWF_ACTION * actions,int maxn,int is_type2)1925 decompileENUMERATE(int n, SWF_ACTION *actions, int maxn, int is_type2)
1926 {
1927 	int i=0;
1928 	while (i < maxn && i < 5 && OpCode(actions, n+i, maxn))
1929 		i++;
1930 
1931 	INDENT
1932 	println("/* a for-var-in  loop should follow below: */" );
1933 	return i-1;		// preserve some code for decompileIF()...
1934 } 				// ... and let decompileIF() do all the dirty work ;-)
1935 
1936 
1937 #ifdef DECOMP_SWITCH
1938 
1939 // [recursive] estimate size of buffer needed for decompiling 'switch'
1940 // [ only call by decompileIF() ]
1941 //
1942 static int
countAllSwitchActions(union SWF_ACTION * actions,union SWF_ACTION * pre)1943 countAllSwitchActions (union SWF_ACTION *actions, union SWF_ACTION *pre)
1944 {
1945 	int i,j=1;
1946 	if (actions->SWF_ACTIONRECORD.ActionCode==SWFACTION_IF && pre->SWF_ACTIONRECORD.ActionCode==SWFACTION_STRICTEQUALS )
1947 	{
1948 		for(i=0; i < ((struct SWF_ACTIONIF*)actions)->numActions; i++)
1949 		{
1950 			j+=countAllSwitchActions(&((struct SWF_ACTIONIF*)actions)->Actions[i],pre);
1951 			pre=&((struct SWF_ACTIONIF*)actions)->Actions[i];
1952 		}
1953 	}
1954 	return j;
1955 }
1956 
1957 
1958 // [recursive] copy all actions in a 'flat' buffer by
1959 // unpackung all if-actions that are part of the switch operation
1960 // [ only call by decompileIF() ]
1961 //
1962 static union SWF_ACTION *
getAllSwitchActions(union SWF_ACTION * dest,union SWF_ACTION * actions,union SWF_ACTION * pre)1963 getAllSwitchActions(union SWF_ACTION *dest, union SWF_ACTION *actions, union SWF_ACTION *pre)
1964 {
1965 #ifdef DEBUGSWITCH
1966 	println("SWCODE: %p %d %s   %s",
1967 	        dest, actions->SWF_ACTIONRECORD.Offset,
1968 	        actionName(actions->SWF_ACTIONRECORD.ActionCode),
1969 	        actionName(pre->SWF_ACTIONRECORD.ActionCode));
1970 #endif
1971 
1972 	*dest++=*actions;
1973 	if (actions->SWF_ACTIONRECORD.ActionCode==SWFACTION_IF
1974 	    && pre->SWF_ACTIONRECORD.ActionCode==SWFACTION_STRICTEQUALS )
1975 	{
1976 		int i;
1977 		struct SWF_ACTIONIF *sactv2 = (struct SWF_ACTIONIF*)actions;
1978 		for(i=0; i< sactv2->numActions; i++)
1979 		{
1980 			dest=getAllSwitchActions(dest,&sactv2->Actions[i],pre);
1981 			pre=&((struct SWF_ACTIONIF*)actions)->Actions[i];
1982 		}
1983 	}
1984 	return dest;
1985 }
1986 
1987 // looks similar other decompileXXXX() but
1988 // can't called by decompileAction()
1989 // [ do only call by decompileIF() ]
1990 //
1991 static int
decompile_SWITCH(int n,SWF_ACTION * actions,int maxn,int off1end)1992 decompile_SWITCH(int n, SWF_ACTION *actions, int maxn, int off1end)
1993 {
1994 	int i,j;
1995 	int start;		// base action index for case value and code
1996 	int ccsize=0;		// size of code for case value
1997 	int cvsize=0;		// size of case value
1998 	int maxoff=0;		// action offset AFTER switch
1999 	int n_maxoff=0;		// array index of maxoff
2000 	int pend=0;		// control pending output
2001 	int xsize=0;		// ret val
2002 	int jmpsize=0;		// debug helper
2003 	int lastoff=0;		// debug helper
2004 	int n_firstactions=maxn;// array index of 1st case actions code
2005 	int lastcasestart=0;	// offs where last "case x:" begins
2006 	char *defa="[last]";	// debug helper for early "default:"
2007 	char *tmp=NULL;		// helper for pending output
2008 	struct strbufinfo origbuf;	// pending output buffer
2009 	struct _stack *StackSave;
2010 	struct SWF_ACTIONPUSHPARAM *swcopy,*sw=pop();
2011 	struct SWF_ACTIONPUSHPARAM *compare=pop();
2012 	int offSave;
2013 	for (i=0; i<n_firstactions; i++) // seek last op in 1st if
2014 	{
2015 		if (actions[i+1].SWF_ACTIONRECORD.Offset==off1end)
2016 		{
2017 			// println("found #off end first= %d",i+1);
2018 			if (OpCode(actions, i, maxn) == SWFACTION_JUMP)
2019 			{
2020 				maxoff=actions[i].SWF_ACTIONJUMP.BranchOffset+actions[i].SWF_ACTIONJUMP.Offset+5;
2021 				j=1;
2022 			}
2023 			else
2024 			{
2025 				// SanityCheck(decompile_SWITCH,0,"no jump found where expected");
2026 			}
2027 			break;
2028 		}
2029 	}
2030 
2031 	if (!maxoff)
2032 	{
2033 		for (i=maxn-1;i>=0;i--)			// seek from end of block last op of switch{}
2034 		{
2035 			if (OpCode(actions, i, maxn) == SWFACTION_JUMP && !actions[i].SWF_ACTIONJUMP.BranchOffset)
2036 			{
2037 				maxoff=actions[i].SWF_ACTIONRECORD.Offset+5;
2038 				j=2;
2039 				break;
2040 			}
2041 		}
2042 	}
2043 
2044 	for (i=0;i<maxn;i++)
2045 	{
2046 		if (actions[i].SWF_ACTIONRECORD.Offset>=maxoff)
2047 		{
2048 			n_maxoff=i;		// part of block is switch
2049 			break;
2050 		}
2051 	}
2052 
2053 	if (!n_maxoff)
2054 		n_maxoff=maxn;			// whole block is switch
2055 
2056 	INDENT
2057 	println("switch( %s ) {			// end switch at %d (index %d) / found via meth %d)",
2058 	        getString(sw), maxoff,n_maxoff,j);
2059 
2060 	push(sw);
2061 	push(compare);
2062 
2063 	i=1;
2064 	do 					// here we go into main loop
2065 	{
2066 		if((OpCode(actions, i, maxn) == SWFACTION_IF
2067 		   && OpCode(actions, i-1, maxn) == SWFACTION_STRICTEQUALS )
2068 		   ||(OpCode(actions, i, maxn) == SWFACTION_JUMP
2069 		   && OpCode(actions, i-1, maxn) == SWFACTION_IF) )
2070 		{
2071 			start=i;
2072 			while (start<maxn
2073 			       && actions[start].SWF_ACTIONRECORD.Offset < actions[i].SWF_ACTIONRECORD.Offset+5+actions[i].SWF_ACTIONJUMP.BranchOffset
2074 )			{
2075 				start++;		// count actions until start of "case x:"
2076 			}
2077 			if (n_firstactions==maxn) // if not done store earliest "case x: "actions
2078 			{
2079 				n_firstactions=start;	// same as array index
2080 			}
2081 
2082 			for (ccsize=0; ccsize+start<n_maxoff; ccsize++)	// count actions belonging to "case x:"
2083 			{
2084 #ifdef DEBUGSWITCH
2085 				println("in ccsize: ccsize=%d  off=%d %s",
2086 				        ccsize,actions[ccsize+start].SWF_ACTIONRECORD.Offset,
2087 				        actionName(actions[ccsize+start].SWF_ACTIONRECORD.ActionCode));
2088 #endif
2089 				if (OpCode(actions, ccsize+start, maxn) == SWFACTION_JUMP)
2090 				{
2091 					if (maxoff == actions[ccsize+start].SWF_ACTIONJUMP.Offset+5 + actions[ccsize+start].SWF_ACTIONJUMP.BranchOffset)
2092 					{
2093 						jmpsize= actions[ccsize+start].SWF_ACTIONJUMP.BranchOffset;
2094 						lastoff= actions[ccsize+start].SWF_ACTIONJUMP.Offset;
2095 						ccsize++; // the jmp itself
2096 						break;
2097 					}
2098 				}
2099 			}
2100 
2101 #if USE_LIB
2102 			if (tmp && (start!=pend)) // output pending buffer if neccessary
2103 			{
2104 				puts(tmp);
2105 			}
2106 
2107 			if (tmp)
2108 			{
2109 				free(tmp);
2110 				tmp=NULL;
2111 			}
2112 			pend=start;
2113 #endif
2114 			if (actions[i].SWF_ACTIONRECORD.ActionCode==SWFACTION_JUMP)
2115 			{
2116 				if (ccsize<=1)
2117 					break;	// ready
2118 				else
2119 				{
2120 					INDENT
2121 					if (actions[start].SWF_ACTIONRECORD.Offset>lastcasestart)
2122 						xsize+=ccsize;
2123 					else
2124 						defa="[early]";
2125 						println("default:			// at %d %s start=%d ccsize=%d",
2126 						        actions[start].SWF_ACTIONRECORD.Offset,defa, start, ccsize);
2127 				}
2128 			}
2129 			else
2130 			{
2131 				INDENT
2132 				xsize=ccsize;
2133 				lastcasestart=actions[start].SWF_ACTIONRECORD.Offset;
2134 				println("case %s:			// at %d  start=%d ccsize=%d jmp=%d+%d+5",
2135 			        getString(pop()), lastcasestart, start, ccsize, lastoff,jmpsize);
2136 				swcopy=pop();
2137 				//   SanityCheck(decompile_SWITCH,!strcmp(getName(swcopy),getName(sw)),"sw0 != sw");
2138 			}
2139 
2140 #if USE_LIB
2141 			origbuf=setTempString(); // switch to temp buffer
2142 #endif
2143 			StackSave=Stack;
2144 			offSave=offseoloop;
2145 			offseoloop=maxoff;
2146 			decompileActions( ccsize, &actions[start],gIndent+1);
2147 			offseoloop=offSave;
2148 			Stack=StackSave;
2149 #if USE_LIB
2150 			tmp=switchToOrigString(origbuf);
2151 #endif
2152 
2153 			if (actions[i].SWF_ACTIONRECORD.ActionCode==SWFACTION_JUMP)		// after "default:"
2154 			{
2155 				break;     							// ready
2156 			}
2157 			else
2158 			{
2159 				if (actions[i+1].SWF_ACTIONRECORD.ActionCode!=SWFACTION_JUMP) 	// not before "default:" or end
2160 				{
2161 					i++; // the 'if' itself
2162 					cvsize=0;
2163 					while (i+cvsize < n_firstactions
2164 					       && actions[i+cvsize].SWF_ACTIONRECORD.ActionCode!=SWFACTION_STRICTEQUALS)
2165 					{
2166 #ifdef DEBUGSWITCH
2167 						println("in  cvsize=%d  %d %s",
2168 						        cvsize, actions[i+cvsize].SWF_ACTIONRECORD.Offset,
2169 						        actionName(actions[i+cvsize].SWF_ACTIONRECORD.ActionCode));
2170 #endif
2171 							cvsize++;	// count "case X:" code size
2172 					}
2173 					decompileActions( cvsize, &actions[i],gIndent+1); // at least one push on stack expected
2174 					i+=cvsize;
2175 				}
2176 			}
2177 		}
2178 	} while (++i < n_firstactions);
2179 
2180 #if USE_LIB
2181 	if (tmp)
2182 	{
2183 		puts(tmp);		// print last pending output
2184 		free(tmp);
2185 	}
2186 #endif
2187 	INDENT
2188 	println("}					// switch ret value =%d",xsize);
2189 	return xsize;
2190 }
2191 #endif
2192 
2193 static int
decompileIF(int n,SWF_ACTION * actions,int maxn)2194 decompileIF(int n, SWF_ACTION *actions, int maxn)
2195 {
2196 	int offSave;
2197 	int j,i=0;
2198 	struct strbufinfo origbuf;
2199 	OUT_BEGIN2(SWF_ACTIONIF);
2200 	/*
2201 	* IF is used in various way to implement different types
2202 	* of loops. We try to detect these different types of loops
2203 	* here.
2204 	*/
2205 
2206 #ifdef STATEMENT_CLASS
2207 	if((OpCode(actions, n-1, maxn) == SWFACTION_LOGICALNOT) &&
2208 	   (OpCode(actions, n-2, maxn) == SWFACTION_LOGICALNOT) &&
2209 	   (OpCode(actions, n-3, maxn) == SWFACTION_GETVARIABLE) &&
2210 	   (OpCode(actions, n-4, maxn) == SWFACTION_PUSH) )
2211 	{
2212 	    /* It's really a class definition */
2213 		INDENT
2214 		puts("class ");
2215 		decompilePUSHPARAM(newVar(getName(pop())),0);
2216 		println(" {" );
2217 		decompileActions(sact->numActions, sact->Actions,gIndent+1);
2218 		INDENT
2219 		println("}");
2220 		return 0;
2221 	}
2222 
2223 	if(
2224 	   (OpCode(actions, n-1, maxn) == SWFACTION_LOGICALNOT) &&
2225 	   (OpCode(actions, n-2, maxn) == SWFACTION_LOGICALNOT) &&
2226 	   (OpCode(actions, n-3, maxn) == SWFACTION_GETMEMBER) &&
2227 	   (OpCode(actions, n-4, maxn) == SWFACTION_PUSH) )
2228 	{
2229 	    /* It's really a class definition */
2230 		INDENT
2231 		println(" {");
2232 		decompileActions(sact->numActions, sact->Actions,gIndent+1);
2233 		INDENT
2234 		println("}");
2235 		return 0;
2236 	}
2237 #endif
2238 	/*
2239 	 * do {} while() loops have a JUMP at the end of the if clause
2240 	 * that points to a JUMP above the IF statement.
2241 	 */
2242 	if(n && isLogicalOp(n-1, actions, maxn) &&
2243 	   (sact->Actions[sact->numActions-1].SWF_ACTIONRECORD.ActionCode == SWFACTION_JUMP) &&
2244 	   ( (sact->Actions[sact->numActions-1].SWF_ACTIONJUMP.Offset +
2245 	      sact->Actions[sact->numActions-1].SWF_ACTIONJUMP.BranchOffset) < actions[n].SWF_ACTIONRECORD.Offset) &&
2246 	      isLogicalOp(sact->numActions-2, sact->Actions, maxn) )
2247 	{
2248 		INDENT
2249 		println("do {");
2250 		offSave=offseoloop;
2251 		offseoloop=actions[n].SWF_ACTIONRECORD.Offset+5;
2252 		decompileActions(sact->numActions-1, sact->Actions,gIndent+1);
2253 		offseoloop=offSave;
2254 		INDENT
2255 		puts("while( ");
2256 		puts(getName(pop()));
2257 		puts(");");
2258 		return 0;
2259 	}
2260 
2261 	/* ak,2006
2262 	 * lots of "do {} while()" have simply a CONDITIONED JUMP back at the end of the loop
2263 	 */
2264 	if( actions[n].SWF_ACTIONJUMP.BranchOffset < 0 )
2265 	{
2266 		INDENT
2267 		println("do {                  /* 2nd type */ ");
2268 		offSave=offseoloop;
2269 		offseoloop=actions[n  ].SWF_ACTIONRECORD.Offset+5;
2270 		decompileActions(sact->numActions, sact->Actions,gIndent+1);
2271 		offseoloop=offSave;
2272 		INDENT
2273 		puts("} while( ");
2274 		puts(getName(pop()));
2275 		println(");");
2276 		return 0;
2277 	}
2278 
2279 	j=0;
2280 	while (OpCode(actions, n-j, maxn) != SWFACTION_ENUMERATE  &&
2281 	        OpCode(actions, n-j, maxn) != SWFACTION_ENUMERATE2 && j<n && j<5)
2282 	{
2283 		j++;		// check for a pending ENUMERATE
2284 	}
2285 
2286 	if ((OpCode(actions, n-j, maxn) == SWFACTION_ENUMERATE ||
2287 	     OpCode(actions, n-j, maxn) == SWFACTION_ENUMERATE2 ) &&
2288 	      OpCode(actions, n-j+1, maxn) == SWFACTION_STOREREGISTER )
2289 	{
2290 		struct SWF_ACTIONPUSHPARAM *var;
2291 		int x;
2292 		var = pop();
2293 		INDENT
2294 		puts("for ( ");
2295 		// check for an usual special case w register Rx
2296 		if (sact->Actions[1].SWF_ACTIONRECORD.ActionCode == SWFACTION_STOREREGISTER)
2297 		{
2298 			struct SWF_ACTIONSTOREREGISTER *sactv2 = (struct SWF_ACTIONSTOREREGISTER*)&sact->Actions[1];
2299 			puts("var ");
2300 			puts(getName(regs[sactv2->Register]));
2301 			x=3;
2302 		}
2303 		else
2304 		{
2305 			decompileActions( 2 , sact->Actions,-1);   /* -1 == the ENUM workaround */
2306 			x=2;
2307 		}
2308 		puts(" in ");
2309 		puts(getName(var));
2310 		println(" ) {");
2311 		if(n+1 >= maxn)
2312 		{
2313 			SWF_warn("Warning: %s:%i: something is wrong here\n", __FILE__, __LINE__);
2314 		}
2315 		else
2316 		{
2317 			offSave=offseoloop;
2318 			offseoloop=actions[n+1].SWF_ACTIONRECORD.Offset;
2319 			decompileActions(sact->numActions-1-x, &sact->Actions[x],gIndent+1);
2320 			offseoloop=offSave;
2321 		}
2322 		INDENT
2323 		println("}");
2324 		return 0;
2325 	}
2326 
2327 	/*
2328 	 * while() loops have a JUMP at the end of the if clause that jumps backwards
2329 	 * But also "continue" statements could jump backwards.
2330 	 */
2331 
2332 	if( isLogicalOp(n-1, actions, maxn) &&
2333 	    ( (sact->Actions[sact->numActions-1].SWF_ACTIONRECORD.ActionCode == SWFACTION_JUMP) &&
2334 	       sact->Actions[sact->numActions-1].SWF_ACTIONJUMP.BranchOffset < 0) )
2335 	{
2336 		if(0)	    dumpRegs();
2337 		INDENT
2338 		/* if on a level >0 we can check for any outer loop
2339 		   To do: get the level on a better way than using gIndent */
2340 		if (gIndent
2341 		    && actions[maxn-1].SWF_ACTIONRECORD.ActionCode==SWFACTION_JUMP
2342 	  	    && actions[maxn-1].SWF_ACTIONJUMP.Offset+actions[maxn].SWF_ACTIONJUMP.BranchOffset==
2343 	               sact->Actions[sact->numActions-1].SWF_ACTIONJUMP.Offset+sact->Actions[sact->numActions-1].SWF_ACTIONJUMP.BranchOffset)
2344 		{
2345 		   /* this jump leads from a block to start of a loop on outer block:
2346 		       it is an 'if' later followed by last action 'continue' */
2347 		   SWF_warn("WARNING: this might be wrong (%s:%i)\n", __FILE__, __LINE__);
2348 		   puts("if ( ");
2349 		   puts(getName(pop()));
2350 		   println(" ) {");
2351 		   decompileActions(sact->numActions, sact->Actions,gIndent+1);
2352 		}
2353 		else	/* while(){}  as usual */
2354 		{
2355 			puts("while( ");
2356 			puts(getName(pop()));
2357 			println(" ) {");
2358 			offSave=offseoloop;
2359 			offseoloop=actions[n+1].SWF_ACTIONRECORD.Offset;
2360 			decompileActions(sact->numActions-1, sact->Actions,gIndent+1);
2361 			offseoloop=offSave;
2362 		}
2363 		INDENT
2364 		println("}");
2365 		return 0;
2366 	}
2367 	{ // WTF ???
2368 #define SOME_IF_DEBUG 0	/* coders only */
2369 		int has_else_or_break= ((sact->Actions[sact->numActions-1].SWF_ACTIONRECORD.ActionCode == SWFACTION_JUMP) &&
2370 			(sact->Actions[sact->numActions-1].SWF_ACTIONJUMP.BranchOffset > 0 )) ? 1:0;
2371 		int has_lognot=(actions[n-1].SWF_ACTIONRECORD.ActionCode == SWFACTION_LOGICALNOT) ? 1:0;
2372 		int else_action_cnt=0,is_logor=0,is_logand=0,sbi,sbe;
2373 
2374 		/* before emitting any "if"/"else" characters let's check
2375 			for a ternary operation  cond?a:b
2376 		*/
2377 		if (has_else_or_break)
2378 		{
2379 			int limit=actions[n+1].SWF_ACTIONRECORD.Offset + sact->Actions[sact->numActions-1].SWF_ACTIONJUMP.BranchOffset;
2380 			/* Count the number of action records that are part of
2381 			 * the else clause, and then decompile only that many.
2382 			 */
2383 			for(else_action_cnt=0;
2384 			    else_action_cnt+n+1<maxn && actions[n+1+else_action_cnt].SWF_ACTIONRECORD.Offset < limit;
2385 			    else_action_cnt++)
2386 			{
2387 #if SOME_IF_DEBUG
2388 				println("/* ELSE OP 0x%x at %d*/",actions[n+1+else_action_cnt].SWF_ACTIONRECORD.ActionCode,
2389 				actions[n+1+else_action_cnt].SWF_ACTIONRECORD.Offset)
2390 #endif
2391 				;
2392 			}
2393 		}
2394 		i=else_action_cnt; 		// =return value
2395 		sbi=stackVal (sact->numActions-1,sact->Actions);
2396 		sbe=stackVal (else_action_cnt,&actions[n+1]);
2397 
2398 		// check against opcodes we do not expect in a ternary operation
2399 		if (sbi==1 && sbe==1)
2400 	   	{
2401 			for (j=0;j<sact->numActions-1;j++)
2402 			{
2403 				if (sact->Actions[j].SWF_ACTIONRECORD.ActionCode==SWFACTION_JUMP) // perhaps more ops
2404 				{
2405 					sbi=i=has_else_or_break=0;
2406 					break;
2407 				}
2408 			}
2409 			for (j=0;j<else_action_cnt;j++)
2410 			{
2411 				if (actions[n+j].SWF_ACTIONRECORD.ActionCode==SWFACTION_JUMP) // perhaps more ops
2412 				{
2413 					sbe=i=has_else_or_break=0;
2414 					break;
2415 				}
2416 			}
2417 		}
2418 #if SOME_IF_DEBUG
2419 		printf("sbi=%d   sbe=%d\n", sbi,sbe);
2420 #endif
2421 		if (sbi==1 && sbe==1)
2422 		{
2423 #if SOME_IF_DEBUG
2424 			println("/* ****Found ternary ternary operation  \"cond ? a : b\"    **** */");
2425 			printf("If   Actions=%d\n",sact->numActions-1);
2426 			printf("Else Actions=%d\n",else_action_cnt);
2427 #endif
2428 			struct strbufinfo origbuf;
2429 #if USE_LIB
2430 			origbuf=setTempString();	/* switch to a temporary string buffer */
2431 #endif
2432 			puts("(");
2433 			puts(getName(pop()));
2434 			puts(" ? ");
2435 			decompileActions(else_action_cnt  , &actions[n+1],0);
2436 			puts(getName(pop()));
2437 			puts(" : ");
2438 			decompileActions(sact->numActions-1, sact->Actions,0);
2439 			puts(getName(pop()));
2440 			puts(")");
2441 #if USE_LIB
2442 			push (newVar(dcgetstr()));	/* push for later assignment */
2443 			setOrigString(origbuf);		/* switch back to orig buffer */
2444 #else
2445 			push (newVar("/* ternary op: see code above */"));
2446 #endif
2447 		}
2448 		else
2449 		{
2450 		/* at this point let's check for conditioned jumps that are NOT 'if':
2451 	      	currently that is code for the locical operations  && and ||
2452 	   	*/
2453 			if (OpCode(actions, n-1, maxn) == SWFACTION_PUSHDUP)
2454 				is_logor=1;
2455 
2456 			if (OpCode(actions, n-2, maxn)== SWFACTION_PUSHDUP
2457 			    && OpCode(actions, n-1, maxn) == SWFACTION_LOGICALNOT)
2458 			{
2459 				is_logand=1;
2460 			}
2461 
2462 		if (is_logor || is_logand)
2463 		{
2464 #if SOME_IF_DEBUG
2465 			println("");
2466 			println("/* detected LOGICAL %s: %d actions*/", is_logor ? "OR":"AND",sact->numActions);
2467 #endif
2468 #if USE_LIB
2469 			origbuf=setTempString();	/* switch to a temporary string buffer */
2470 #endif
2471 
2472 			puts(getName(pop()));	/* get left side of logical or */
2473 			puts(is_logor ? " || ":" && ");
2474 			decompileActions(sact->numActions, sact->Actions,gIndent+1);
2475 			puts(getName(pop()));	/* get right side of logical or */
2476 #if USE_LIB
2477 			push(newVar(dcgetstr()));
2478 			setOrigString(origbuf);	/* switch back to orig buffer */
2479 #else
2480 			push (newVar("/* see logical term lines above */"));
2481 #endif
2482 			return 0;
2483 		}
2484 #ifdef DECOMP_SWITCH
2485 		if ( OpCode(actions, n-1, maxn) == SWFACTION_STRICTEQUALS
2486 		     && check_switch(sact->Actions[0].SWF_ACTIONRECORD.ActionCode) )
2487 		{
2488 			union SWF_ACTION *xact,*xact0;
2489 			for(i=n-1,j=0; i< maxn ;i++)	// n-1 due adding 1st SWFACTION_STRICTEQUALS in buffer
2490 			{
2491 				j+=countAllSwitchActions(&actions[i],&actions[i-1]); 		// FIRST count size of code
2492 			}
2493 			xact0=xact = (union SWF_ACTION *) calloc (j,sizeof (SWF_ACTION));
2494 			INDENT
2495 			println("// checking %d actions for switch(){}",j);
2496 			for(i=n-1; i< maxn ;i++)
2497 			{
2498 				xact=getAllSwitchActions(xact,&actions[i],&actions[i-1]);	// SECOND copy into xtra buffer
2499 			}
2500 			j=decompile_SWITCH(0,xact0,j,actions[n+1].SWF_ACTIONRECORD.Offset);	// THIRD decompile xtra buffer
2501 			free(xact0);
2502 			return j;
2503 		}
2504 #endif
2505 		/* it seems we have a found the REAL 'if' statement,
2506 		so it's right time to print the "if" just NOW!
2507 		*/
2508 		INDENT
2509 		puts("if( ");
2510 		puts(getName(pop()));	/* the condition itself */
2511 		println(" ) {");
2512 		if ( has_else_or_break )
2513 		{
2514 			int limit=actions[n+1].SWF_ACTIONRECORD.Offset + sact->Actions[sact->numActions-1].SWF_ACTIONJUMP.BranchOffset;
2515 			// limit == dest of jmp == offset next op after 'if' + jumpdist at end of 'if'
2516 			int lastopsize=actions[maxn-1].SWF_ACTIONRECORD.Length;
2517 			if (actions[maxn-1].SWF_ACTIONRECORD.ActionCode == SWFACTION_IF)
2518 				lastopsize+=actions[maxn-1].SWF_ACTIONIF.BranchOffset + 3; /* +3 see parser.c: "Action + Length bytes not included in the length" */
2519 
2520 			if (offseoloop
2521 			    &&  ! (has_lognot
2522 			    && OpCode(actions, n-2, maxn) == SWFACTION_EQUALS2
2523 			    && OpCode(actions, n-3, maxn) == SWFACTION_PUSH
2524 			    && OpCode(actions, n-4, maxn) == SWFACTION_PUSHDUP)
2525 			    && limit > actions[maxn-1].SWF_ACTIONRECORD.Offset+lastopsize)
2526 			{
2527 				/* the jump leads outside this limit, so it is a simple 'if'
2528 				with a 'break' or 'return' at the end, and there is NO else clause.
2529 				*/
2530 				INDENT
2531 				println("// offs_endjump_dest=%d  offs_after_blk %d",
2532 				        limit, actions[maxn-1].SWF_ACTIONRECORD.Offset+lastopsize);
2533 				decompileActions(sact->numActions, sact->Actions,gIndent+1);
2534 				i=0;			/* found break/return but no else and thus return 0 */
2535 			}
2536 			else
2537 			{
2538 				/* There is an else clause also!
2539 				(action counter is set above)
2540 				*/
2541 				struct _stack *StackSave=Stack;	/* decompile if and else blocks at same stack base */
2542 				if  (has_lognot)
2543 				{
2544 					decompileActions(sact->numActions-1, sact->Actions,gIndent+1);
2545 					INDENT
2546 					println("} else {");
2547 				}
2548 				Stack=StackSave;
2549 				decompileActions(else_action_cnt  , &actions[n+1],gIndent+1);
2550 				if  (!has_lognot)		/* the missing if-part just NOW */
2551 				{
2552 					Stack=StackSave;
2553 					INDENT
2554 					println ("} else {" );
2555 					decompileActions(sact->numActions-1, sact->Actions,gIndent+1);
2556 				}
2557 			}
2558 		}
2559 		else
2560 		{
2561 			/* It's a simple if() {} */
2562 			decompileActions(sact->numActions, sact->Actions,gIndent+1);
2563 		}
2564 		INDENT
2565 		println("}");
2566 	} // WTF ???
2567 	return i;
2568 	}
2569 	return 0;
2570 }
2571 
2572 static int
decompileINITOBJECT(int n,SWF_ACTION * actions,int maxn)2573 decompileINITOBJECT(int n, SWF_ACTION *actions, int maxn)
2574 {
2575 	struct SWF_ACTIONPUSHPARAM *nparam;
2576 	nparam=pop();
2577 	push(newVar_N2("","","","{", nparam->p.Integer,"}"));
2578 	return 0;
2579 }
2580 
2581 static int
decompileWITH(int n,SWF_ACTION * actions,int maxn)2582 decompileWITH(int n, SWF_ACTION *actions, int maxn)
2583 {
2584 	OUT_BEGIN2(SWF_ACTIONWITH);
2585 
2586 	INDENT
2587 	puts("with(");
2588 	decompilePUSHPARAM(pop(),0);
2589 	puts(")");
2590 	println(" {" );
2591 	decompileActions(sact->numActions, sact->Actions,gIndent+1);
2592 	INDENT
2593 	println("}" );
2594 
2595 	return 1;
2596 }
2597 
2598 static int
decompileTRY(int n,SWF_ACTION * actions,int maxn)2599 decompileTRY(int n, SWF_ACTION *actions, int maxn)
2600 {
2601 #ifdef DEBUG
2602 	struct _stack *StackSave=Stack;
2603 #endif
2604 	OUT_BEGIN2(SWF_ACTIONTRY);
2605 	INDENT
2606 	println("try {");
2607 	decompileActions(sact->numTryActs, sact->TryActs,gIndent+1);
2608 	INDENT
2609 	println("}");
2610 #ifdef DEBUG
2611 	if (Stack!=StackSave)
2612 	{
2613 		println("/* Stack problem in try{} code above */");
2614 		Stack=StackSave;
2615 	}
2616 #endif
2617 	if (sact->numCatchActs)
2618 	{
2619 		struct SWF_ACTIONPUSHPARAM *rsave=NULL;
2620 		INDENT
2621 		if( ! sact->CatchInRegisterFlag)
2622 			println("catch (%s) {",sact->CatchName);
2623 		else
2624 		{
2625 			char *t=malloc(5); /* Rddd */
2626 			sprintf(t,"R%d", sact->CatchRegister );
2627 			rsave=regs[sact->CatchRegister];
2628 			regs[sact->CatchRegister] = newVar(t);
2629 			println("catch (%s) {",t);
2630 		}
2631 		decompileActions(sact->numCatchActs, sact->CatchActs,gIndent+1);
2632 		INDENT
2633 		println("}");
2634 		if (rsave)
2635 			regs[sact->CatchRegister]=rsave;
2636 #ifdef DEBUG
2637 		if (Stack!=StackSave)
2638 		{
2639 			println("/* Stack problem in catch{} code above */");
2640 			Stack=StackSave;
2641 		}
2642 #endif
2643 	}
2644 	if (sact->numFinallyActs)
2645 	{
2646 		INDENT
2647 		println("finally () {");
2648 		decompileActions(sact->numFinallyActs, sact->FinallyActs,gIndent+1);
2649 		INDENT
2650 		println("}");
2651 #ifdef DEBUG
2652 		if (Stack!=StackSave)
2653 		{
2654 			println("/* Stack problem in finally{} code above */");
2655 			Stack=StackSave;
2656 		}
2657 #endif
2658 	}
2659 	return 0;
2660 }
2661 
2662 
2663 static int
decompileDEFINEFUNCTION(int n,SWF_ACTION * actions,int maxn,int is_type2)2664 decompileDEFINEFUNCTION(int n, SWF_ACTION *actions, int maxn, int is_type2)
2665 {
2666 	int i,j,k,m,r;
2667 	struct SWF_ACTIONPUSHPARAM *myregs[ 256 ];
2668 	struct _stack *StackSave;
2669 	struct SWF_ACTIONDEFINEFUNCTION2 *sactv2;
2670 	struct strbufinfo origbuf;
2671 	OUT_BEGIN2(SWF_ACTIONDEFINEFUNCTION);
2672 	sactv2 = (struct SWF_ACTIONDEFINEFUNCTION2*)sact;
2673 
2674 #ifdef DEBUG
2675 	if(n+1 < maxn)
2676 	{
2677 		println("/* function followed by OP %x */",
2678 		        OpCode(actions, n+1, maxn));
2679 	}
2680 #endif
2681 #if USE_LIB
2682 	if (isStoreOp(n+1, actions,maxn)
2683 	    || (  *sact->FunctionName==0 && !is_type2 )
2684 	    || (*sactv2->FunctionName==0 && is_type2  ))
2685 	{
2686 		origbuf=setTempString();	/* switch to a temporary string buffer */
2687 	}
2688 #endif
2689 	puts("function ");
2690 	if (is_type2)
2691 	{
2692 		for(j=1;j<sactv2->RegisterCount;j++)
2693 		{
2694 			myregs[j]=regs[j];
2695 			regs[j]=NULL;
2696 		}
2697 		r=1;
2698 		if (sactv2->PreloadThisFlag)	regs[r++]=newVar("this");
2699 		if (sactv2->PreloadArgumentsFlag)	regs[r++]=newVar("arguments");
2700 		if (sactv2->PreloadSuperFlag)	regs[r++]=newVar("super");
2701 		if (sactv2->PreloadRootFlag)	regs[r++]=newVar("root");
2702 		if (sactv2->PreloadParentFlag)	regs[r++]=newVar("parent");
2703 		if (sactv2->PreloadGlobalFlag)	regs[r++]=newVar("global");
2704 
2705 		puts(sactv2->FunctionName);
2706 		puts("(");
2707 
2708 		for(i=0,m=0;i<sactv2->NumParams;i++)
2709 		{
2710 			puts(sactv2->Params[i].ParamName);
2711 			if ( sactv2->Params[i].Register)
2712 			{
2713 				 printf(" /*=R%d*/ ",sactv2->Params[i].Register);
2714 				 regs[sactv2->Params[i].Register] = newVar(sactv2->Params[i].ParamName);
2715 				 m++;					// do not count 'void' etc
2716 			}
2717 			if( sactv2->NumParams > i+1 ) puts(",");
2718 		}
2719 		println(") {" );
2720 		if (r+m < sactv2->RegisterCount)
2721 		{
2722 			INDENT
2723 			puts("  var ");
2724 		}
2725 		for(k=r;r<sactv2->RegisterCount;r++)
2726 		{
2727 			if (!regs[r])
2728 			{
2729 				char *t=malloc(5); /* Rddd */
2730 				sprintf(t,"R%d", r );
2731 				puts (t);
2732 				if (k++ < sactv2->RegisterCount- m -1)
2733 					puts(", ");
2734 				else
2735 					println(";" );
2736 				regs[r]=newVar(t);
2737 			}
2738 		}
2739 		StackSave=Stack;
2740 		decompileActions(sactv2->numActions, sactv2->Actions,gIndent+1);
2741 #ifdef DEBUG
2742 		if (Stack!=StackSave)
2743 		{
2744 			println("/* Stack problem in function code above */");
2745 		}
2746 #endif
2747 		Stack=StackSave;
2748 		for(j=1;j<sactv2->RegisterCount;j++)
2749 			regs[j]=myregs[j];
2750 	}
2751 	else
2752 	{
2753 		puts(sact->FunctionName);
2754 		puts("(");
2755 		for(i=0;i<sact->NumParams;i++) {
2756 			puts(sact->Params[i]);
2757 			if( sact->NumParams > i+1 ) puts(",");
2758 		}
2759 		println(") {" );
2760 		k=0;
2761 		if (sact->Actions[0].SWF_ACTIONRECORD.ActionCode == SWFACTION_PUSH)
2762 		{
2763 			struct SWF_ACTIONPUSH *sactPush=(struct SWF_ACTIONPUSH *)sact->Actions;
2764 			for(i=0;i<sactPush->NumParam;i++)
2765 			{
2766 				if ((&(sactPush->Params[i]))->Type == PUSH_REGISTER)
2767 					k++;	/* REGISTER */
2768 			}
2769 			if (k)
2770 			{
2771 				INDENT
2772 				puts("  var ");
2773 				for(i=1;i<=k;i++)
2774 				{
2775 					char *t=malloc(5); /* Rddd */
2776 					sprintf(t,"R%d", i );
2777 					puts (t);
2778 					if (i < k)
2779 						puts(", ");
2780 					else
2781 						println(";" );
2782 					regs[i]=newVar(t);
2783 				}
2784 			}
2785 		}
2786 		for(j=1;j<=k;j++)
2787 			myregs[j]=regs[j];
2788 		StackSave=Stack;
2789 		decompileActions(sact->numActions, sact->Actions,gIndent+1);
2790 #ifdef DEBUG
2791 		if (Stack!=StackSave)
2792 		{
2793 			println("/* Stack problem in function code above */");
2794 		}
2795 #endif
2796 		Stack=StackSave;
2797 		for(j=1;j<=k;j++)
2798 			regs[j]=myregs[j];
2799 	}
2800 	INDENT
2801 	if (isStoreOp(n+1, actions,maxn)
2802 	    || ( *sact->FunctionName==0 && !is_type2 )
2803 	    || (*sactv2->FunctionName==0 && is_type2 ))
2804 	{
2805 		puts("}");
2806 #if USE_LIB
2807 		push (newVar(dcgetstr()));	/* push func body for later assignment */
2808 		setOrigString(origbuf);		/* switch back to orig buffer */
2809 #else
2810 		push (newVar("/* see function code above */"));	/* workaround only if LIB is not in use */
2811 #endif
2812 	}
2813 	else
2814 		println("}" );
2815 	return 0;
2816 }
2817 
2818 static int
decompileCALLMETHOD(int n,SWF_ACTION * actions,int maxn)2819 decompileCALLMETHOD(int n, SWF_ACTION *actions, int maxn)
2820 {
2821 	struct SWF_ACTIONPUSHPARAM *meth, *obj, *nparam;
2822 	meth=pop();
2823 	obj=pop();
2824 	nparam=pop();
2825 	if (nparam->p.Integer>25)
2826 	{
2827 		INDENT
2828 		println("// Problem getting method arguments (%d ignored) below:",
2829 		        nparam->p.Integer);
2830 		nparam->p.Integer=0;
2831 	}
2832 #ifdef DEBUG
2833 	printf("*CALLMethod* objName=%s (type=%d) methName=%s (type=%d)\n",
2834 		getName(obj), obj->Type, getName(meth), meth->Type);
2835 #endif
2836 	if (meth->Type == PUSH_UNDEF) 	/* just undefined, like in "super();" */
2837 		push(newVar_N(getName(obj),"","","(", nparam->p.Integer,")"));
2838 	else
2839 	{
2840 		if (meth->Type == PUSH_INT || meth->Type == PUSH_DOUBLE || meth->Type == PUSH_VARIABLE
2841 		    || meth->Type == PUSH_REGISTER || meth->Type == 12 )
2842 		{
2843 			push(newVar_N(getName(obj),"[",getName(meth),"](", nparam->p.Integer,")"));
2844 		}
2845 		else
2846 			push(newVar_N(getName(obj),".",getName(meth),"(", nparam->p.Integer,")"));
2847 	}
2848 	if (OpCode(actions, n+1, maxn) == SWFACTION_POP)
2849 	{
2850 		/* call method and throw away any result */
2851 		INDENT
2852 		puts(getName(pop()));
2853 		println(";" );
2854 		return 1;
2855 	}
2856 	return 0;
2857 }
2858 
2859 static int
decompileCALLFUNCTION(int n,SWF_ACTION * actions,int maxn)2860 decompileCALLFUNCTION(int n, SWF_ACTION *actions, int maxn)
2861 {
2862 	struct SWF_ACTIONPUSHPARAM *meth, *nparam;
2863 
2864 	SanityCheck(SWF_CALLMETHOD,
2865 		actions[n-1].SWF_ACTIONRECORD.ActionCode == SWFACTION_PUSH,
2866 		"CALLMETHOD not preceeded by PUSH")
2867 
2868 	meth=pop();
2869 	nparam=pop();
2870 	if (nparam->p.Integer>25)
2871 	{
2872 		INDENT
2873 		println("// Problem getting function arguments (%d ignored) below:",
2874 			nparam->p.Integer);
2875 		nparam->p.Integer=0;
2876 	}
2877 	push(newVar_N("","",getName(meth),"(", nparam->p.Integer,")"));
2878 	if (OpCode(actions, n+1, maxn) == SWFACTION_POP)
2879 	{
2880 		/* call function and throw away any result */
2881 		INDENT
2882 		puts(getName(pop()));
2883 		println(";" );
2884 		return 1;
2885 	}
2886 	return 0;
2887 }
2888 
2889 static int
decompile_Null_ArgBuiltInFunctionCall(int n,SWF_ACTION * actions,int maxn,char * functionname)2890 decompile_Null_ArgBuiltInFunctionCall(int n, SWF_ACTION *actions, int maxn, char *functionname)
2891 {
2892 	INDENT
2893 	puts(functionname);		// only used for cases w/o return value
2894 	println("();" );
2895 	return 0;
2896 }
2897 
2898 static int
decompileSingleArgBuiltInFunctionCall(int n,SWF_ACTION * actions,int maxn,char * functionname)2899 decompileSingleArgBuiltInFunctionCall(int n, SWF_ACTION *actions, int maxn, char *functionname)
2900 {
2901 	push(newVar_N("","",functionname,"(", 1,")"));
2902 	if (OpCode(actions, n+1, maxn) == SWFACTION_POP)
2903 	{
2904 		/* call function and throw away any result */
2905 		INDENT
2906 		puts(getName(pop()));
2907 		println(";" );
2908 		return 1;
2909 	}
2910 	return 0;
2911 }
2912 
2913 static int
decompileSTARTDRAG(int n,SWF_ACTION * actions,int maxn)2914 decompileSTARTDRAG(int n, SWF_ACTION *actions, int maxn)
2915 {
2916 	INDENT
2917 	puts("startDrag(");
2918 	decompilePUSHPARAM(pop(),1);
2919 	puts(",");
2920 	decompilePUSHPARAM(pop(),0);
2921 	puts(",");
2922 	decompilePUSHPARAM(pop(),0);	//
2923 	println(");" );
2924 	return 0;
2925 }
2926 
2927 static int
decompileSUBSTRING(int n,SWF_ACTION * actions,int maxn)2928 decompileSUBSTRING(int n, SWF_ACTION *actions,int maxn)
2929 {
2930 	push(newVar_N("","","substr","(", 3,")"));
2931 	if (OpCode(actions, n+1, maxn) == SWFACTION_POP)
2932 	{
2933 		/* call function and throw away any result */
2934 		INDENT
2935 		puts(getName(pop()));
2936 		println(";" );
2937 		return 1;
2938 	}
2939 	return 0;
2940 }
2941 
2942 static int
decompileSTRINGCONCAT(int n,SWF_ACTION * actions,int maxn)2943 decompileSTRINGCONCAT(int n, SWF_ACTION *actions, int maxn)
2944 {
2945 	push(newVar_N("","","concat","(", 2,")"));
2946 	if (OpCode(actions, n+1, maxn) == SWFACTION_POP)
2947 	{
2948 		/* call function and throw away any result */
2949 		INDENT
2950 		puts(getName(pop()));
2951 		println(";" );
2952 		return 1;
2953 	}
2954 	return 0;
2955 }
2956 
2957 static int
decompileTHROW(int n,SWF_ACTION * actions,int maxn)2958 decompileTHROW(int n, SWF_ACTION *actions, int maxn)
2959 {
2960 	INDENT
2961 	puts("throw ");
2962 	puts(getName(pop()));
2963 	println(";");
2964 	return 0;
2965 }
2966 
2967 static int
decompileREMOVECLIP(int n,SWF_ACTION * actions,int maxn)2968 decompileREMOVECLIP(int n, SWF_ACTION *actions, int maxn)
2969 {
2970 	INDENT
2971 	puts("removeMovieClip(");
2972 	puts(getName(pop()));
2973 	println(");" );
2974 	return 0;
2975 }
2976 
2977 static int
decompileDUPLICATECLIP(int n,SWF_ACTION * actions,int maxn)2978 decompileDUPLICATECLIP(int n, SWF_ACTION *actions, int maxn)
2979 {
2980 	struct SWF_ACTIONPUSHPARAM *a, *b;
2981 
2982 	INDENT
2983 	a = pop();
2984 	b = pop();
2985 
2986 	puts("duplicateMovieClip(");
2987 	puts(getString(pop()));
2988 	puts(",");
2989 	puts(getString(b));
2990 	puts(",");
2991 	puts(getString(a));
2992 	println(");" );
2993 	return 0;
2994 }
2995 
2996 static int
decompileINITARRAY(int n,SWF_ACTION * actions,int maxn)2997 decompileINITARRAY(int n, SWF_ACTION *actions, int maxn)
2998 {
2999 	struct SWF_ACTIONPUSHPARAM *nparam;
3000 	nparam=pop();
3001 	push(newVar_N("","","","[", nparam->p.Integer,"]"));
3002 	return 0;
3003 }
3004 
3005 static int
decompileEXTENDS(int n,SWF_ACTION * actions,int maxn)3006 decompileEXTENDS(int n, SWF_ACTION *actions, int maxn)
3007 {
3008 	struct SWF_ACTIONPUSHPARAM *baseclass;
3009 
3010 	baseclass=pop();
3011 #if 0
3012 	/* It's useless to open a class body when there's no
3013 	 * other code supporting it. */
3014 	printf("class ");
3015 	puts(getName(pop()));
3016 	printf(" extends ");
3017 	puts(getName(baseclass));
3018 	println(" {" );
3019 #else
3020 	/* We'll do it with asm{} */
3021 	println("asm {");
3022 	println(" push '%s'", getName(pop()));
3023 	println(" getvariable");
3024 	println(" push '%s'", getName(baseclass));
3025 	println(" getvariable");
3026 	println(" extends");
3027 	println("};");
3028 #endif
3029 
3030 	return 0;
3031 }
3032 
3033 static int
decompileDELETE(int n,SWF_ACTION * actions,int maxn,int is_type2)3034 decompileDELETE(int n, SWF_ACTION *actions, int maxn, int is_type2)
3035 {
3036 	if (is_type2)
3037 		push(newVar3("delete(",getName(pop()),")"));
3038 	else
3039 		push(newVar_N("delete(",getName(pop()),".",getName(pop()), 0,")"));
3040 
3041 
3042 	if (OpCode(actions, n+1, maxn) == SWFACTION_POP)
3043 	{
3044 		/* call delete() with its args and throw away any result */
3045 		INDENT
3046 		puts(getName(pop()));
3047 		println(";" );
3048 		return 1;
3049 	}
3050 	return 0;
3051 }
3052 
3053 static int
decompileSETTARGET(int n,SWF_ACTION * actions,int maxn,int is_type2)3054 decompileSETTARGET(int n, SWF_ACTION *actions, int maxn, int is_type2)
3055 {
3056 	int action_cnt=0;
3057 	char *name;
3058 	OUT_BEGIN2(SWF_ACTIONSETTARGET);
3059 	name = is_type2 ? getString(pop()) : sact->TargetName;
3060 	if (*name)
3061 	{
3062 		INDENT
3063 		println("tellTarget('%s') {" ,name);
3064 		while(action_cnt+n<maxn)
3065 		{
3066 			if (OpCode(actions, n+1+action_cnt, maxn)==SWFACTION_SETTARGET
3067 			    || OpCode(actions, n+1+action_cnt, maxn)==SWFACTION_SETTARGET2
3068 			    || OpCode(actions, n+1+action_cnt, maxn)==SWFACTION_DEFINEFUNCTION
3069 			    || OpCode(actions, n+1+action_cnt, maxn)==SWFACTION_DEFINEFUNCTION2
3070 			    || OpCode(actions, n+1+action_cnt, maxn)==SWFACTION_END)
3071 			{
3072 				break;
3073 			}
3074 			action_cnt++;
3075 		}
3076 		decompileActions(action_cnt,&actions[n+1],gIndent+1);
3077 		INDENT
3078 		println("}" );
3079 	}
3080 	return action_cnt;
3081 }
3082 
3083 static int
decompileIMPLEMENTS(int n,SWF_ACTION * actions,int maxn)3084 decompileIMPLEMENTS(int n, SWF_ACTION *actions, int maxn)
3085 {
3086 	struct SWF_ACTIONPUSHPARAM *nparam;
3087 	int i;
3088 	INDENT;
3089 	puts(getName(pop()));
3090 	printf(" implements ");
3091 	nparam=pop();
3092 	for(i=0;i<nparam->p.Integer;i++)
3093 	{
3094 		puts(getName(pop()));
3095 	}
3096 	println(" ;");
3097 	return 0;
3098 }
3099 
3100 static int
decompileCAST(int n,SWF_ACTION * actions,int maxn)3101 decompileCAST(int n, SWF_ACTION *actions, int maxn)
3102 {
3103 	struct SWF_ACTIONPUSHPARAM *iparam=pop();
3104 	struct SWF_ACTIONPUSHPARAM *tparam=pop();
3105 	push(newVar_N( getName(tparam),"(",getName(iparam),"", 0,")"));
3106 	return 0;
3107 }
3108 
3109 int
decompileAction(int n,SWF_ACTION * actions,int maxn)3110 decompileAction(int n, SWF_ACTION *actions, int maxn)
3111 {
3112 	if( n > maxn ) SWF_error("Action overflow!!");
3113 
3114 #ifdef DEBUG
3115 	fprintf(stderr,"%d:\tACTION[%3.3d]: %s\n",
3116 	        actions[n].SWF_ACTIONRECORD.Offset, n,
3117 	        actionName(actions[n].SWF_ACTIONRECORD.ActionCode));
3118 #endif
3119 
3120 	switch(actions[n].SWF_ACTIONRECORD.ActionCode)
3121 	{
3122 	case SWFACTION_END:
3123 		return 0;
3124 
3125 	case SWFACTION_CONSTANTPOOL:
3126 		decompileCONSTANTPOOL(&actions[n]);
3127 		return 0;
3128 
3129 	case SWFACTION_GOTOLABEL:
3130 		return decompileGOTOFRAME(n, actions, maxn,1);
3131 
3132 	case SWFACTION_GOTOFRAME:
3133 		return decompileGOTOFRAME(n, actions, maxn,0);
3134 
3135 	case SWFACTION_GOTOFRAME2:
3136 		return decompileGOTOFRAME2(n, actions, maxn);
3137 
3138 	case SWFACTION_WAITFORFRAME:
3139 		decompileWAITFORFRAME(&actions[n]);
3140 		return 0;
3141 
3142 	case SWFACTION_GETURL2:
3143 		decompileGETURL2(&actions[n]);
3144 		return 0;
3145 
3146 	case SWFACTION_GETURL:
3147 		decompileGETURL(&actions[n]);
3148 		return 0;
3149 
3150 	case SWFACTION_PUSH:
3151 		decompilePUSH(&actions[n]);
3152 		return 0;
3153 
3154 	case SWFACTION_PUSHDUP:
3155 		decompilePUSHDUP(&actions[n]);
3156 		return 0;
3157 
3158 	case SWFACTION_STACKSWAP:
3159 		decompileSTACKSWAP(&actions[n]);
3160 		return 0;
3161 
3162 	case SWFACTION_SETPROPERTY:
3163 		decompileSETPROPERTY(n, actions, maxn);
3164 		return 0;
3165 
3166 	case SWFACTION_GETPROPERTY:
3167 		decompileGETPROPERTY(n, actions, maxn);
3168 		return 0;
3169 
3170 	case SWFACTION_GETTIME:
3171 		return decompileGETTIME(n, actions, maxn);
3172 
3173 	case SWFACTION_TRACE:
3174 		decompileTRACE(n, actions, maxn);
3175 		return 0;
3176 
3177 	case SWFACTION_CALLFRAME:
3178 		decompileCALLFRAME(n, actions, maxn);
3179 		return 0;
3180 
3181 	case SWFACTION_EXTENDS:
3182 		decompileEXTENDS(n, actions, maxn);
3183 		return 0;
3184 
3185 	case SWFACTION_INITOBJECT:
3186 		decompileINITOBJECT(n, actions, maxn);
3187 		return 0;
3188 
3189 	case SWFACTION_NEWOBJECT:
3190 		decompileNEWOBJECT(n, actions, maxn);
3191 		return 0;
3192 
3193 	case SWFACTION_NEWMETHOD:
3194 		decompileNEWMETHOD(n, actions, maxn);
3195 		return 0;
3196 
3197 	case SWFACTION_GETMEMBER:
3198 		decompileGETMEMBER(n, actions, maxn);
3199 		return 0;
3200 
3201 	case SWFACTION_SETMEMBER:
3202 		decompileSETMEMBER(n, actions, maxn);
3203 		return 0;
3204 
3205 	case SWFACTION_GETVARIABLE:
3206 		decompileGETVARIABLE(n, actions, maxn);
3207 		return 0;
3208 
3209 	case SWFACTION_SETVARIABLE:
3210 		decompileSETVARIABLE(n, actions, maxn, 0);
3211 		return 0;
3212 
3213 	case SWFACTION_DEFINELOCAL:
3214 		decompileSETVARIABLE(n, actions, maxn, 1);
3215 		return 0;
3216 
3217 	case SWFACTION_DEFINELOCAL2:
3218 		decompileDEFINELOCAL2(n, actions, maxn);
3219 		return 0;
3220 
3221 	case SWFACTION_DECREMENT:
3222 		return decompileINCR_DECR(n, actions, maxn, 0);
3223 
3224 	case SWFACTION_INCREMENT:
3225 		return decompileINCR_DECR(n, actions, maxn,1);
3226 
3227 	case SWFACTION_STOREREGISTER:
3228 		decompileSTOREREGISTER(n, actions, maxn);
3229 		return 0;
3230 
3231 	case SWFACTION_JUMP:
3232 		return decompileJUMP(n, actions, maxn);
3233 
3234 	case SWFACTION_RETURN:
3235 		decompileRETURN(n, actions, maxn);
3236 		return 0;
3237 
3238 	case SWFACTION_LOGICALNOT:
3239 		return decompileLogicalNot(n, actions, maxn);
3240 
3241 	case SWFACTION_IF:
3242 		return decompileIF(n, actions, maxn);
3243 
3244 	case SWFACTION_WITH:
3245 		decompileWITH(n, actions, maxn);
3246 		return 0;
3247 
3248 	case SWFACTION_ENUMERATE:
3249 		return decompileENUMERATE(n, actions, maxn, 0);
3250 
3251 	case SWFACTION_ENUMERATE2 :
3252 		return decompileENUMERATE(n, actions, maxn,1);
3253 
3254 	case SWFACTION_INITARRAY:
3255 		return decompileINITARRAY(n, actions, maxn);
3256 
3257 	case SWFACTION_DEFINEFUNCTION:
3258 		return decompileDEFINEFUNCTION(n, actions, maxn,0);
3259 
3260 	case SWFACTION_DEFINEFUNCTION2:
3261 		return decompileDEFINEFUNCTION(n, actions, maxn,1);
3262 
3263 	case SWFACTION_CALLFUNCTION:
3264 		return decompileCALLFUNCTION(n, actions, maxn);
3265 
3266 	case SWFACTION_CALLMETHOD:
3267 		return decompileCALLMETHOD(n, actions, maxn);
3268 
3269 	case SWFACTION_INSTANCEOF:
3270 	case SWFACTION_SHIFTLEFT:
3271 	case SWFACTION_SHIFTRIGHT:
3272 	case SWFACTION_SHIFTRIGHT2:
3273 	case SWFACTION_ADD:
3274 	case SWFACTION_ADD2:
3275 	case SWFACTION_SUBTRACT:
3276 	case SWFACTION_MULTIPLY:
3277 	case SWFACTION_DIVIDE:
3278 	case SWFACTION_MODULO:
3279 	case SWFACTION_BITWISEAND:
3280 	case SWFACTION_BITWISEOR:
3281 	case SWFACTION_BITWISEXOR:
3282 	case SWFACTION_EQUAL:
3283 	case SWFACTION_EQUALS2:
3284 	case SWFACTION_LESS2:
3285 	case SWFACTION_LOGICALAND:
3286 	case SWFACTION_LOGICALOR:
3287 	case SWFACTION_GREATER:
3288 	case SWFACTION_LESSTHAN:
3289 	case SWFACTION_STRINGEQ:
3290 	case SWFACTION_STRINGCOMPARE:
3291 	case SWFACTION_STRICTEQUALS:
3292 		return decompileArithmeticOp(n, actions, maxn);
3293 
3294 	case SWFACTION_POP:
3295 		pop();
3296 		return 0;
3297 
3298 	case SWFACTION_STARTDRAG:
3299 		return decompileSTARTDRAG(n, actions, maxn);
3300 
3301 	case SWFACTION_DELETE:
3302 		return decompileDELETE(n, actions, maxn,0);
3303 
3304 	case SWFACTION_DELETE2:
3305 		return decompileDELETE(n, actions, maxn,1);
3306 
3307 	case SWFACTION_TARGETPATH:
3308 		return decompileSingleArgBuiltInFunctionCall(n, actions, maxn,"targetPath");
3309 
3310 	case SWFACTION_TYPEOF:
3311 		return decompileSingleArgBuiltInFunctionCall(n, actions, maxn,"typeof");
3312 
3313 	case SWFACTION_ORD:
3314 		return decompileSingleArgBuiltInFunctionCall(n, actions, maxn,"ord");
3315 
3316 	case SWFACTION_CHR:
3317 		return decompileSingleArgBuiltInFunctionCall(n, actions, maxn,"chr");
3318 
3319 	case SWFACTION_INT:
3320 		return decompileSingleArgBuiltInFunctionCall(n, actions, maxn,"int");
3321 
3322 	case SWFACTION_TOSTRING:
3323 		return decompileSingleArgBuiltInFunctionCall(n, actions, maxn,"String");
3324 
3325 	case SWFACTION_TONUMBER:
3326 		return decompileSingleArgBuiltInFunctionCall(n, actions, maxn,"Number");
3327 
3328 	case SWFACTION_RANDOMNUMBER:
3329 		return decompileSingleArgBuiltInFunctionCall(n, actions, maxn,"random");
3330 
3331 	case SWFACTION_STRINGLENGTH:
3332 		return decompileSingleArgBuiltInFunctionCall(n, actions, maxn,"length");
3333 
3334 	case SWFACTION_PLAY:
3335 		return decompile_Null_ArgBuiltInFunctionCall(n, actions, maxn,"play");
3336 
3337 	case SWFACTION_STOP:
3338 		return decompile_Null_ArgBuiltInFunctionCall(n, actions, maxn,"stop");
3339 
3340 	case SWFACTION_NEXTFRAME:
3341 		return decompile_Null_ArgBuiltInFunctionCall(n, actions, maxn,"nextFrame");
3342 
3343 	case SWFACTION_PREVFRAME:
3344 		return decompile_Null_ArgBuiltInFunctionCall(n, actions, maxn,"prevFrame");
3345 
3346 	case SWFACTION_ENDDRAG:
3347 		return decompile_Null_ArgBuiltInFunctionCall(n, actions, maxn,"stopDrag");
3348 
3349 	case SWFACTION_STOPSOUNDS:
3350 		return decompile_Null_ArgBuiltInFunctionCall(n, actions, maxn,"stopAllSounds");
3351 
3352 	case SWFACTION_TOGGLEQUALITY:
3353 		return decompile_Null_ArgBuiltInFunctionCall(n, actions, maxn,"toggleHighQuality");
3354 
3355 	case SWFACTION_MBSUBSTRING:
3356 	case SWFACTION_SUBSTRING:
3357 		return decompileSUBSTRING(n, actions, maxn);
3358 
3359 	case SWFACTION_STRINGCONCAT:
3360 		return decompileSTRINGCONCAT(n, actions, maxn);
3361 
3362 	case SWFACTION_REMOVECLIP:
3363 		return decompileREMOVECLIP(n, actions, maxn);
3364 
3365 	case SWFACTION_DUPLICATECLIP:
3366 		return decompileDUPLICATECLIP(n, actions, maxn);
3367 
3368 	case SWFACTION_SETTARGET:
3369 		return decompileSETTARGET(n, actions, maxn,0);
3370 
3371 	case SWFACTION_SETTARGET2:
3372 		return decompileSETTARGET(n, actions, maxn,1);
3373 
3374 	case SWFACTION_IMPLEMENTSOP:
3375 		return decompileIMPLEMENTS(n, actions, maxn);
3376 
3377 	case SWFACTION_CASTOP:
3378 		return decompileCAST(n, actions, maxn);
3379 
3380 	case SWFACTION_THROW:
3381 		return decompileTHROW(n, actions, maxn);
3382 
3383 	case SWFACTION_TRY:
3384 		return decompileTRY(n, actions, maxn);
3385 
3386 	default:
3387 		outputSWF_ACTION(n,&actions[n]);
3388 		return 0;
3389 	}
3390 }
3391 
3392 static void
decompileActions(int n,SWF_ACTION * actions,int indent)3393 decompileActions(int n, SWF_ACTION *actions, int indent)
3394 {
3395 	int i, svindent;
3396 
3397 	svindent = gIndent;
3398 	gIndent = indent;
3399 
3400 	for(i=0;i<n;i++) {
3401 		i+=decompileAction(i, actions, n);
3402 	}
3403 	gIndent = svindent;
3404 }
3405 
3406 char *
decompile5Action(int n,SWF_ACTION * actions,int indent)3407 decompile5Action(int n, SWF_ACTION *actions,int indent)
3408 {
3409 	int j;
3410 	if( !n  )
3411 		return NULL;
3412 
3413 	pool = NULL;
3414 
3415 	dcinit();
3416 
3417 	for(j=0;j<256;j++) regs[j]=0;
3418 	regs[1] = newVar("R1");
3419 	regs[2] = newVar("R2");
3420 	regs[3] = newVar("R3");
3421 	regs[4] = newVar("R4");
3422 
3423 	decompileActions(n, actions, indent);
3424 #ifdef DEBUGSTACK
3425 	if( Stack != NULL && *dcstr)
3426 	{
3427 		int i=0;
3428 		println("/* -----------------------------------------------------------------");
3429 		println("NOTE: some stuff left on the stack at the end of a block of actions:");
3430 		while (Stack)
3431 		{
3432 			i++;
3433 			printf("%d.:\t%s",i, getString(pop()));
3434 			println("");
3435 		}
3436 		println("*/");
3437 	}
3438 #else
3439 	if( Stack != NULL )
3440 		fprintf(stderr,
3441 		"Stuff left on the stack at the end of a block of actions!?!?!?\n");
3442 	while (Stack)
3443 	{
3444 		pop();
3445 	}
3446 #endif
3447 	return dcgetstr();
3448 }
3449 
3450