I do not know if this qualifies as digging up an old post or not; but I think the following code would be useful to someone somehow
I have an updated version specifically for ionCube 6 & 7 if I can find it...
Code:
/***********************************************************************/
/* */
/* FILE :dezender.c */
/* DATE :2005/08/10 */
/* DESCRIPTION :opcode->php source code */
/* PROJECT :deZender */
/* */
/***********************************************************************/
#include "php.h"
#include "ext/standard/url.h"
#if 0
#define ZEND_NOP 0 /* NOP */
#define ZEND_ADD 1 /* + */
#define ZEND_SUB 2 /* - */
#define ZEND_MUL 3 /* * */
#define ZEND_DIV 4 /* / */
#define ZEND_MOD 5 /* % */
#define ZEND_SL 6 /* << */
#define ZEND_SR 7 /* >> */
#define ZEND_CONCAT 8 /* . */
#define ZEND_BW_OR 9 /* | */
#define ZEND_BW_AND 10 /* & */
#define ZEND_BW_XOR 11 /* ^ */
#define ZEND_BW_NOT 12 /* ~ */
#define ZEND_BOOL_NOT 13 /* ! */
#define ZEND_BOOL_XOR 14 /* XOR */
#define ZEND_IS_IDENTICAL 15 /* === */
#define ZEND_IS_NOT_IDENTICAL 16 /* !== */
#define ZEND_IS_EQUAL 17 /* == */
#define ZEND_IS_NOT_EQUAL 18 /* != */
#define ZEND_IS_SMALLER 19 /* < */
#define ZEND_IS_SMALLER_OR_EQUAL 20 /* <= */
#define ZEND_CAST 21 /* (int), (real), (string), (array), (object), (bool), (unset) */
#define ZEND_QM_ASSIGN 22 /* a?b:c */
#define ZEND_ASSIGN_ADD 23 /* += */
#define ZEND_ASSIGN_SUB 24 /* -= */
#define ZEND_ASSIGN_MUL 25 /* *= */
#define ZEND_ASSIGN_DIV 26 /* /= */
#define ZEND_ASSIGN_MOD 27 /* %= */
#define ZEND_ASSIGN_SL 28 /* <<= */
#define ZEND_ASSIGN_SR 29 /* >>= */
#define ZEND_ASSIGN_CONCAT 30 /* .= */
#define ZEND_ASSIGN_BW_OR 31 /* |= */
#define ZEND_ASSIGN_BW_AND 32 /* &= */
#define ZEND_ASSIGN_BW_XOR 33 /* ^= */
#define ZEND_PRE_INC 34 /* ++a */
#define ZEND_PRE_DEC 35 /* --a */
#define ZEND_POST_INC 36 /* a++ */
#define ZEND_POST_DEC 37 /* a-- */
#define ZEND_ASSIGN 38 /* = */
#define ZEND_ASSIGN_REF 39 /* =&a */
#define ZEND_ECHO 40 /* echo */
#define ZEND_PRINT 41 /* print */
#define ZEND_JMP 42 /* JMP */
#define ZEND_JMPZ 43 /* JMPZ */
#define ZEND_JMPNZ 44 /* JMPNZ */
#define ZEND_JMPZNZ 45 /* JMPZNZ */
#define ZEND_JMPZ_EX 46 /* JMPZ_EX */
#define ZEND_JMPNZ_EX 47 /* JMPNZ_EX */
#define ZEND_CASE 48 /* case */
#define ZEND_SWITCH_FREE 49 /* return, foreach, switch */
#define ZEND_BRK 50 /* break */
#define ZEND_CONT 51 /* continue */
#define ZEND_BOOL 52 /* ||, &&, switch(expr), default: */
#define ZEND_INIT_STRING 53 /* '' */
#define ZEND_ADD_CHAR 54 /* . */
#define ZEND_ADD_STRING 55 /* . */
#define ZEND_ADD_VAR 56 /* . */
#define ZEND_BEGIN_SILENCE 57 /* @:begin */
#define ZEND_END_SILENCE 58 /* @:end */
#define ZEND_INIT_FCALL_BY_NAME 59 /* call function */
#define ZEND_DO_FCALL 60 /* call function */
#define ZEND_DO_FCALL_BY_NAME 61 /* call function */
#define ZEND_RETURN 62 /* return */
#define ZEND_RECV 63 /* function parameter */
#define ZEND_RECV_INIT 64 /* function parameter: static? */
#define ZEND_SEND_VAL 65 /* function call parameter: without variable */
#define ZEND_SEND_VAR 66 /* function call parameter: variable */
#define ZEND_SEND_REF 67 /* function call parameter: &variable */
#define ZEND_NEW 68 /* new */
#define ZEND_JMP_NO_CTOR 69 /* free, end of new */
#define ZEND_FREE 70 /* free */
#define ZEND_INIT_ARRAY 71 /* array pair list (a => b, ...) */
#define ZEND_ADD_ARRAY_ELEMENT 72 /* array pair list (a => b, ...) */
#define ZEND_INCLUDE_OR_EVAL 73 /* include, include_once, evel, require, require_once */
#define ZEND_UNSET_VAR 74 /* unset variable */
#define ZEND_UNSET_DIM_OBJ 75 /* unset dim, unset object */
#define ZEND_ISSET_ISEMPTY 76 /* isset, empty */
#define ZEND_FE_RESET 77 /* foreach */
#define ZEND_FE_FETCH 78 /* foreach */
#define ZEND_EXIT 79 /* exit */
#define ZEND_FETCH_R 80 /* fetch variable: read mode */
#define ZEND_FETCH_DIM_R 81 /* fetch dim: read mode */
#define ZEND_FETCH_OBJ_R 82 /* fetch object: read mode */
#define ZEND_FETCH_W 83 /* fetch variable: write mode */
#define ZEND_FETCH_DIM_W 84 /* fetch dim: write mode */
#define ZEND_FETCH_OBJ_W 85 /* fetch object: write mode */
#define ZEND_FETCH_RW 86 /* fetch variable: read/write mode */
#define ZEND_FETCH_DIM_RW 87 /* fetch dim: read/write mode */
#define ZEND_FETCH_OBJ_RW 88 /* fetch object: read/write mode */
#define ZEND_FETCH_IS 89 /* fetch variable: is mode */
#define ZEND_FETCH_DIM_IS 90 /* fetch dim: is mode */
#define ZEND_FETCH_OBJ_IS 91 /* fetch object: is mode */
#define ZEND_FETCH_FUNC_ARG 92 /* fetch variable: argument mode */
#define ZEND_FETCH_DIM_FUNC_ARG 93 /* fetch dim: argument mode */
#define ZEND_FETCH_OBJ_FUNC_ARG 94 /* fetch object: argument mode */
#define ZEND_FETCH_UNSET 95 /* fetch unset variable */
#define ZEND_FETCH_DIM_UNSET 96 /* fetch unset dim */
#define ZEND_FETCH_OBJ_UNSET 97 /* fetch unset object */
#define ZEND_FETCH_DIM_TMP_VAR 98 /* list, foreach */
#define ZEND_FETCH_CONSTANT 99 /* constant declaration */
#define ZEND_DECLARE_FUNCTION_OR_CLASS 100 /* function, class */
#define ZEND_EXT_STMT 101 /* ??? */
#define ZEND_EXT_FCALL_BEGIN 102 /* ??? */
#define ZEND_EXT_FCALL_END 103 /* ??? */
#define ZEND_EXT_NOP 104 /* ??? */
#define ZEND_TICKS 105 /* declare (ticks=?) */
#define ZEND_SEND_VAR_NO_REF 106 /* function call parameter: no reference */
#endif
/*-- for php 5.0.4 --*/
#define ZEND_CATCH 107
#define ZEND_THROW 108
#define ZEND_FETCH_CLASS 109
#define ZEND_CLONE 110
#define ZEND_INIT_CTOR_CALL 111
#define ZEND_INIT_METHOD_CALL 112
#define ZEND_INIT_STATIC_METHOD_CALL 113
#define ZEND_ISSET_ISEMPTY_VAR 114
#define ZEND_ISSET_ISEMPTY_DIM_OBJ 115
#define ZEND_IMPORT_FUNCTION 116
#define ZEND_IMPORT_CLASS 117
#define ZEND_IMPORT_CONST 118
#define ZEND_PRE_INC_OBJ 132
#define ZEND_PRE_DEC_OBJ 133
#define ZEND_POST_INC_OBJ 134
#define ZEND_POST_DEC_OBJ 135
#define ZEND_ASSIGN_OBJ 136
#define ZEND_OP_DATA 137
#define ZEND_INSTANCEOF 138
//#define ZEND_DECLARE_CLASS 139
//#define ZEND_DECLARE_INHERITED_CLASS 140
//#define ZEND_DECLARE_FUNCTION 141
#define ZEND_RAISE_ABSTRACT_ERROR 142
#define DEZ_OP_NOP 0 /* NOP */
#define DEZ_OP_ADD 1 /* + */
#define DEZ_OP_SUB 2 /* - */
#define DEZ_OP_MUL 3 /* * */
#define DEZ_OP_DIV 4 /* / */
#define DEZ_OP_MOD 5 /* % */
#define DEZ_OP_SL 6 /* << */
#define DEZ_OP_SR 7 /* >> */
#define DEZ_OP_CONCAT 8 /* . */
#define DEZ_OP_BW_OR 9 /* | */
#define DEZ_OP_BW_AND 10 /* & */
#define DEZ_OP_BW_XOR 11 /* ^ */
#define DEZ_OP_BW_NOT 12 /* ~ */
#define DEZ_OP_BOOL_NOT 13 /* ! */
#define DEZ_OP_IS_IDENTICAL 14 /* === */
#define DEZ_OP_IS_NOT_IDENTICAL 15 /* !== */
#define DEZ_OP_IS_EQUAL 16 /* == */
#define DEZ_OP_IS_NOT_EQUAL 17 /* != */
#define DEZ_OP_IS_SMALLER 18 /* < */
#define DEZ_OP_IS_SMALLER_OR_EQUAL 19 /* <= */
#define DEZ_OP_CAST 20 /* (double)a, (string)a, (array)a, (object)a, (bool)a, (unset)a */
#define DEZ_OP_QM_ASSIGN 21 /* a?b:c */
#define DEZ_OP_ASSIGN_ADD 22 /* += */
#define DEZ_OP_ASSIGN_SUB 23 /* -= */
#define DEZ_OP_ASSIGN_MUL 24 /* *= */
#define DEZ_OP_ASSIGN_DIV 25 /* /= */
#define DEZ_OP_ASSIGN_MOD 26 /* %= */
#define DEZ_OP_ASSIGN_SL 27 /* <<= */
#define DEZ_OP_ASSIGN_SR 28 /* >>= */
#define DEZ_OP_ASSIGN_CONCAT 29 /* .= */
#define DEZ_OP_ASSIGN_BW_OR 30 /* |= */
#define DEZ_OP_ASSIGN_BW_AND 31 /* &= */
#define DEZ_OP_ASSIGN_BW_XOR 32 /* ^= */
#define DEZ_OP_PRE_INC 33 /* ++a */
#define DEZ_OP_PRE_DEC 34 /* --a */
#define DEZ_OP_POST_INC 35 /* a++ */
#define DEZ_OP_POST_DEC 36 /* a-- */
#define DEZ_OP_ASSIGN 37 /* = */
#define DEZ_OP_ASSIGN_REF 38 /* =&a, static, global */
#define DEZ_OP_ECHO 39 /* echo */
#define DEZ_OP_PRINT 40 /* print */
#define DEZ_OP_INCLUDE_OR_EVAL 41 /* include, include_once, eval, require, require_once */
#define DEZ_OP_LOGICAL_OR 42 /* OR */
#define DEZ_OP_LOGICAL_XOR 43 /* XOR */
#define DEZ_OP_LOGICAL_AND 44 /* AND */
#define DEZ_OP_NEW 45 /* new */
#define DEZ_OP_EXIT 46 /* exit */
#define DEZ_OP_IF 47 /* if */
#define DEZ_OP_ELSEIF 48 /* elseif */
#define DEZ_OP_ELSE 49 /* else */
#define DEZ_OP_DO 50 /* do */
#define DEZ_OP_WHILE 51 /* while */
#define DEZ_OP_FOR 52 /* for */
#define DEZ_OP_FOREACH 53 /* foreach */
#define DEZ_OP_DECLARE 54 /* declare */
#define DEZ_OP_AS 55 /* as */
#define DEZ_OP_SWITCH 56 /* switch */
#define DEZ_OP_CASE 57 /* case */
#define DEZ_OP_DEFAULT 58 /* default */
#define DEZ_OP_BREAK 59 /* break */
#define DEZ_OP_CONTINUE 60 /* continue */
#define DEZ_OP_OLD_FUNCTION 61 /* old_function */
#define DEZ_OP_FUNCTION 62 /* function */
#define DEZ_OP_CONST 63 /* const */
#define DEZ_OP_RETURN 64 /* return */
#define DEZ_OP_USE 65 /* use */
#define DEZ_OP_VAR 66 /* var */
#define DEZ_OP_UNSET 67 /* unset */
#define DEZ_OP_ISSET 68 /* isset */
#define DEZ_OP_EMPTY 69 /* empty */
#define DEZ_OP_CLASS 70 /* class */
#define DEZ_OP_EXTENDS 71 /* extends */
#define DEZ_OP_OBJECT_OPERATOR 72 /* a->b */
#define DEZ_OP_DOUBLE_ARROW 73 /* a=>b */
#define DEZ_OP_LIST 74 /* list */
#define DEZ_OP_ARRAY 75 /* array */
#define DEZ_OP_CLASS_C 76 /* __CLASS__ */
#define DEZ_OP_FUNC_C 77 /* __FUNCTION__ */
#define DEZ_OP_LINE 78 /* __LINE__ */
#define DEZ_OP_FILE 79 /* __FILE__ */
#define DEZ_OP_COMMENT 80 /* comment */
#define DEZ_OP_HEREDOC 81 /* <<< */
#define DEZ_OP_DOLLAR_OPEN_CURLY_BRACES 82 /* ${...} */
#define DEZ_OP_PAAMAYIM_NEKUDOTAYIM 83 /* :: */
#define DEZ_OP_CALL_PARAM 84 /* parameter of function calling */
#define DEZ_OP_CALL_INIT 85 /* initialize function calling */
#define DEZ_OP_CALL 86 /* function call */
#define DEZ_OP_CALL_EX 87 /* function call (ex) */
#define DEZ_OP_BOOL 88 /* end of OR, AND, ... */
#define DEZ_OP_FETCH_DIM 89 /* fetch dim */
#define DEZ_OP_INIT_STRING 90 /* init string */
#define DEZ_OP_FETCH 91 /* fetch variable */
#define DEZ_OP_FETCH_CONSTANT 92 /* fetch constant */
#define DEZ_OP_JMP 93 /* jmp */
#define DEZ_OP_FUNC_PARAM 94 /* parameter of function */
#define DEZ_OP_BEGIN_SILENCE 95 /* @: begin */
#define DEZ_OP_END_SILENCE 96 /* @: end */
#define DEZ_OP_LE 97 /* list element */
#define DEZ_OP_UNKNOWN 98 /* unknown op */
#define DEZ_IS_OPLINE (1<<15)
#define DEZ_IS_CLASS (1<<16)
#define OPC_STACK_SIZE 1024
#define OPCS_MAX_LEN 16
#define DEZ_VARS_NUM 1024
#define NODE_STACK_SIZE 2048
#define DEZ_ADD_NODE(x) \
m_dez_op_prev = (x); \
(x)->prev = m_dez_op_current; \
(x)->next = NULL; \
if (m_dez_op_current != NULL) \
{ \
m_dez_op_current->next = (x); \
} \
m_dez_op_current = (x);
#define DEZ_DEL_NODE(x) \
if ((x)->prev != NULL) (x)->prev->next = (x)->next; \
if ((x)->next != NULL) (x)->next->prev = (x)->prev; \
(x)->next = NULL; \
if (m_dez_op_current == (x)) m_dez_op_current = (x)->prev; \
dez_node_specs[(x)->dez_op].dez_node_free_func(x);
#define DEZ_DEL_CURRENT_NODE() \
m_dez_op_current = m_dez_op_current->prev; \
dez_node_specs[m_dez_op_current->next->dez_op].dez_node_free_func(m_dez_op_current->next); \
m_dez_op_current->next = NULL;
#define ZEND_LINENUM(x) \
((x) == NULL ? 0 : ((x) >= (zend_op *)m_zend_op_dup && (x) < (zend_op *)(m_zend_op_dup+m_zend_op_dup_num) ? *((int *)((x)+1)) : ((x) - m_zend_op_start)))
typedef struct
{
zend_op zop;
int linenum;
} DEZ_ZEND_OP_DUP;
typedef struct
{
int index;
char varname[1024];
} DEZ_VAR;
typedef struct DEZ_EG_VAR_NAME_t
{
unsigned type;
char *var;
unsigned len;
unsigned other;
} DEZ_EG_VAR_NAME;
typedef struct DEZ_EG_FUNC_NAME_t
{
unsigned type;
char *func;
unsigned len;
unsigned other;
} DEZ_EG_FUNC_NAME;
typedef struct DEZ_EG_FUNC_t
{
DEZ_EG_FUNC_NAME *funcs;
unsigned func_num;
unsigned r2;
unsigned r3;
} DEZ_EG_FUNC;
typedef struct DEZ_EG_E_t
{
unsigned r1;
unsigned r2;
unsigned r3;
unsigned r4;
unsigned r5;
unsigned r6;
void *p1;
unsigned char *zop2op;
void *p2;
unsigned r7;
void *p3;
unsigned r8;
} DEZ_EG_E;
typedef struct DEZ_EG_RESERVED_t
{
DEZ_EG_VAR_NAME *vars;
unsigned var_num;
unsigned r1;
DEZ_EG_FUNC *funcs;
unsigned r2;
DEZ_EG_E *e;
void *p3;
} DEZ_EG_RESERVED;
/*-- type: dez node --*/
typedef struct DEZ_NODE_s
{
unsigned char dez_op; /* dez op code */
zend_op *zop;
void *content; /* dez node content */
struct DEZ_NODE_s *prev; /* pointer the previous dez node */
struct DEZ_NODE_s *next; /* pointer the next dez node */
} DEZ_NODE;
/*-- dez node content: expression --*/
typedef struct DEZ_NODE_EXPR_s
{
DEZ_NODE *branch_node; /* must is first one */
DEZ_NODE *op1_node;
DEZ_NODE *op2_node;
} DEZ_NODE_EXPR;
/*-- dez node content: if --*/
typedef struct DEZ_NODE_IF_s
{
DEZ_NODE *branch_node; /* must is first one */
DEZ_NODE *op1_node;
DEZ_NODE *op2_node;
int dest;
} DEZ_NODE_IF;
/*-- dez node content: for --*/
typedef struct DEZ_NODE_FOR_s
{
DEZ_NODE *branch_node; /* must is first one */
DEZ_NODE *before_node;
DEZ_NODE *cond_node;
DEZ_NODE *after_node;
} DEZ_NODE_FOR;
/*-- dez node content: => --*/
typedef struct DEZ_NODE_DA_s
{
DEZ_NODE *branch_node; /* must is first one */
DEZ_NODE *key_node;
DEZ_NODE *value_node;
DEZ_NODE *next_node;
} DEZ_NODE_DA;
/*-- dez node content: foreach --*/
typedef struct DEZ_NODE_FOREACH_s
{
DEZ_NODE *branch_node; /* must is first one */
DEZ_NODE *source_node;
DEZ_NODE *key_node;
DEZ_NODE *value_node;
} DEZ_NODE_FOREACH;
/*-- dez node content: function --*/
typedef struct DEZ_NODE_FUNCTION_s
{
DEZ_NODE *branch_node; /* must is first one */
DEZ_NODE *param_node;
char *name;
DEZ_VAR m_dez_vars[DEZ_VARS_NUM];
int m_dez_var_num;
zend_op_array *op_array;
} DEZ_NODE_FUNCTION;
/*-- dez node content: class --*/
typedef struct DEZ_NODE_CLASS_s
{
DEZ_NODE *branch_node; /* must is first one */
char *name;
zend_class_entry *parent;
} DEZ_NODE_CLASS;
/*-- dez node content: var --*/
typedef struct DEZ_NODE_VAR_s
{
DEZ_NODE *branch_node; /* must is first one */
Bucket *property;
} DEZ_NODE_VAR;
/*-- dez node content: list element --*/
typedef struct DEZ_NODE_LE_s
{
DEZ_NODE *branch_node; /* must is first one */
DEZ_NODE *a_node;
int pos;
} DEZ_NODE_LE;
/*-- dez node content: list --*/
typedef struct DEZ_NODE_LIST_s
{
DEZ_NODE *branch_node; /* must is first one */
DEZ_NODE *le_node;
DEZ_NODE *dest_node;
int level;
} DEZ_NODE_LIST;
typedef int (*DEZ_NODE_CVT_FUNC)(unsigned char dez_op, zend_op *pzop);
typedef int (*DEZ_NODE_OUTPUT_FUNC)(DEZ_NODE *pdez_node);
typedef void (*DEZ_NODE_FREE_FUNC)(DEZ_NODE *pdez_node);
static int dez_node_cvt_nop (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_expr (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_qm_assign (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_if (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_do (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_for (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_foreach (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_case (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_default (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_function_or_class (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_double_arrow (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_array (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_heredoc (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_dollar_open_curly_braces (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_call (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_bool (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_jmp (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_func_param (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_unknown (unsigned char dez_op, zend_op *pzop);
static int dez_node_output_nop(DEZ_NODE *pdez_node);
static int dez_node_output_expr(DEZ_NODE *pdez_node);
static int dez_node_output_cast(DEZ_NODE *pdez_node);
static int dez_node_output_pre(DEZ_NODE *pdez_node);
static int dez_node_output_pre2(DEZ_NODE *pdez_node);
static int dez_node_output_post(DEZ_NODE *pdez_node);
static int dez_node_output_qm_assign(DEZ_NODE *pdez_node);
static int dez_node_output_assign(DEZ_NODE *pdez_node);
static int dez_node_output_assign_ref(DEZ_NODE *pdez_node);
static int dez_node_output_include_or_eval(DEZ_NODE *pdez_node);
static int dez_node_output_or_and(DEZ_NODE *pdez_node);
static int dez_node_output_new(DEZ_NODE *pdez_node);
static int dez_node_output_exit(DEZ_NODE *pdez_node);
static int dez_node_output_if(DEZ_NODE *pdez_node);
static int dez_node_output_do(DEZ_NODE *pdez_node);
static int dez_node_output_for(DEZ_NODE *pdez_node);
static int dez_node_output_foreach(DEZ_NODE *pdez_node);
static int dez_node_output_declare(DEZ_NODE *pdez_node);
static int dez_node_output_case(DEZ_NODE *pdez_node);
static int dez_node_output_default(DEZ_NODE *pdez_node);
static int dez_node_output_function(DEZ_NODE *pdez_node);
static int dez_node_output_var(DEZ_NODE *pdez_node);
static int dez_node_output_unset(DEZ_NODE *pdez_node);
static int dez_node_output_isset_or_empty(DEZ_NODE *pdez_node);
static int dez_node_output_class(DEZ_NODE *pdez_node);
static int dez_node_output_double_arrow(DEZ_NODE *pdez_node);
static int dez_node_output_list(DEZ_NODE *pdez_node);
static int dez_node_output_array(DEZ_NODE *pdez_node);
static int dez_node_output_heredoc(DEZ_NODE *pdez_node);
static int dez_node_output_dollar_open_curly_braces(DEZ_NODE *pdez_node);
static int dez_node_output_call_param(DEZ_NODE *pdez_node);
static int dez_node_output_call_init(DEZ_NODE *pdez_node);
static int dez_node_output_call(DEZ_NODE *pdez_node);
static int dez_node_output_call_ex(DEZ_NODE *pdez_node);
static int dez_node_output_fetch_dim(DEZ_NODE *pdez_node);
static int dez_node_output_init_string(DEZ_NODE *pdez_node);
static int dez_node_output_fetch_constant(DEZ_NODE *pdez_node);
static int dez_node_output_func_param(DEZ_NODE *pdez_node);
static int dez_node_output_property(DEZ_NODE *pdez_node);
static int dez_node_output_le(DEZ_NODE *pdez_node);
static int dez_node_output_unknown(DEZ_NODE *pdez_node);
static void dez_node_free_nop (DEZ_NODE *pdez_node);
static void dez_node_free_expr (DEZ_NODE *pdez_node);
static void dez_node_free_if (DEZ_NODE *pdez_node);
static void dez_node_free_for (DEZ_NODE *pdez_node);
static void dez_node_free_foreach (DEZ_NODE *pdez_node);
static void dez_node_free_case (DEZ_NODE *pdez_node);
static void dez_node_free_default (DEZ_NODE *pdez_node);
static void dez_node_free_function (DEZ_NODE *pdez_node);
static void dez_node_free_var (DEZ_NODE *pdez_node);
static void dez_node_free_class (DEZ_NODE *pdez_node);
static void dez_node_free_da (DEZ_NODE *pdez_node);
static void dez_node_free_list (DEZ_NODE *pdez_node);
static void dez_node_free_heredoc (DEZ_NODE *pdez_node);
static void dez_node_free_dollar_open_curly_braces (DEZ_NODE *pdez_node);
static void dez_node_free_property(DEZ_NODE *pdez_node);
static void dez_node_free_le (DEZ_NODE *pdez_node);
static void dez_node_free_unknown (DEZ_NODE *pdez_node);
typedef struct
{
char *desc;
DEZ_NODE_CVT_FUNC dez_node_cvt_func; /* the node convert function */
DEZ_NODE_OUTPUT_FUNC dez_node_output_func; /* the node output function */
DEZ_NODE_FREE_FUNC dez_node_free_func; /* the node free function */
} DEZ_NODE_SPEC;
typedef struct
{
unsigned char dez_op; /* dez op code */
short opcs_len; /* the length of opcs[] */
unsigned char opcs[OPCS_MAX_LEN]; /* the matching zend op codes */
} DEZ_OP_TYPE;
typedef struct DEZ_BRK_CNT_NODE_s
{
const DEZ_NODE *node; /* pointer to if(false) node */
struct DEZ_BRK_CNT_NODE_s *prev;
struct DEZ_BRK_CNT_NODE_s *next;
} DEZ_BRK_CNT_NODE;
static DEZ_VAR m_dez_vars[DEZ_VARS_NUM];
static int m_dez_var_num = 0;
static char *ZEND_OP_STRING[] =
{
"ZEND_NOP ",
"ZEND_ADD ",
"ZEND_SUB ",
"ZEND_MUL ",
"ZEND_DIV ",
"ZEND_MOD ",
"ZEND_SL ",
"ZEND_SR ",
"ZEND_CONCAT ",
"ZEND_BW_OR ",
"ZEND_BW_AND ",
"ZEND_BW_XOR ",
"ZEND_BW_NOT ",
"ZEND_BOOL_NOT ",
"ZEND_BOOL_XOR ",
"ZEND_IS_IDENTICAL ",
"ZEND_IS_NOT_IDENTICAL ",
"ZEND_IS_EQUAL ",
"ZEND_IS_NOT_EQUAL ",
"ZEND_IS_SMALLER ",
"ZEND_IS_SMALLER_OR_EQUAL ",
"ZEND_CAST ",
"ZEND_QM_ASSIGN ",
"ZEND_ASSIGN_ADD ",
"ZEND_ASSIGN_SUB ",
"ZEND_ASSIGN_MUL ",
"ZEND_ASSIGN_DIV ",
"ZEND_ASSIGN_MOD ",
"ZEND_ASSIGN_SL ",
"ZEND_ASSIGN_SR ",
"ZEND_ASSIGN_CONCAT ",
"ZEND_ASSIGN_BW_OR ",
"ZEND_ASSIGN_BW_AND ",
"ZEND_ASSIGN_BW_XOR ",
"ZEND_PRE_INC ",
"ZEND_PRE_DEC ",
"ZEND_POST_INC ",
"ZEND_POST_DEC ",
"ZEND_ASSIGN ",
"ZEND_ASSIGN_REF ",
"ZEND_ECHO ",
"ZEND_PRINT ",
"ZEND_JMP ",
"ZEND_JMPZ ",
"ZEND_JMPNZ ",
"ZEND_JMPZNZ ",
"ZEND_JMPZ_EX ",
"ZEND_JMPNZ_EX ",
"ZEND_CASE ",
"ZEND_SWITCH_FREE ",
"ZEND_BRK ",
"ZEND_CONT ",
"ZEND_BOOL ",
"ZEND_INIT_STRING ",
"ZEND_ADD_CHAR ",
"ZEND_ADD_STRING ",
"ZEND_ADD_VAR ",
"ZEND_BEGIN_SILENCE ",
"ZEND_END_SILENCE ",
"ZEND_INIT_FCALL_BY_NAME ",
"ZEND_DO_FCALL ",
"ZEND_DO_FCALL_BY_NAME ",
"ZEND_RETURN ",
"ZEND_RECV ",
"ZEND_RECV_INIT ",
"ZEND_SEND_VAL ",
"ZEND_SEND_VAR ",
"ZEND_SEND_REF ",
"ZEND_NEW ",
"ZEND_JMP_NO_CTOR ",
"ZEND_FREE ",
"ZEND_INIT_ARRAY ",
"ZEND_ADD_ARRAY_ELEMENT ",
"ZEND_INCLUDE_OR_EVAL ",
"ZEND_UNSET_VAR ",
"ZEND_UNSET_DIM_OBJ ",
"ZEND_ISSET_ISEMPTY ",
"ZEND_FE_RESET ",
"ZEND_FE_FETCH ",
"ZEND_EXIT ",
"ZEND_FETCH_R ",
"ZEND_FETCH_DIM_R ",
"ZEND_FETCH_OBJ_R ",
"ZEND_FETCH_W ",
"ZEND_FETCH_DIM_W ",
"ZEND_FETCH_OBJ_W ",
"ZEND_FETCH_RW ",
"ZEND_FETCH_DIM_RW ",
"ZEND_FETCH_OBJ_RW ",
"ZEND_FETCH_IS ",
"ZEND_FETCH_DIM_IS ",
"ZEND_FETCH_OBJ_IS ",
"ZEND_FETCH_FUNC_ARG ",
"ZEND_FETCH_DIM_FUNC_ARG ",
"ZEND_FETCH_OBJ_FUNC_ARG ",
"ZEND_FETCH_UNSET ",
"ZEND_FETCH_DIM_UNSET ",
"ZEND_FETCH_OBJ_UNSET ",
"ZEND_FETCH_DIM_TMP_VAR ",
"ZEND_FETCH_CONSTANT ",
"ZEND_DECLARE_FUNCTION_OR_CLASS ",
"ZEND_EXT_STMT ",
"ZEND_EXT_FCALL_BEGIN ",
"ZEND_EXT_FCALL_END ",
"ZEND_EXT_NOP ",
"ZEND_TICKS ",
"ZEND_SEND_VAR_NO_REF ",
"ZEND_CATCH ",
"ZEND_THROW ",
"ZEND_FETCH_CLASS ",
"ZEND_CLONE ",
"ZEND_INIT_CTOR_CALL ",
"ZEND_INIT_METHOD_CALL ",
"ZEND_INIT_STATIC_METHOD_CALL ",
"ZEND_ISSET_ISEMPTY_VAR ",
"ZEND_ISSET_ISEMPTY_DIM_OBJ ",
"ZEND_IMPORT_FUNCTION ",
"ZEND_IMPORT_CLASS ",
"ZEND_IMPORT_CONST ",
"ZEND_PRE_INC_OBJ ",
"ZEND_PRE_DEC_OBJ ",
"ZEND_POST_INC_OBJ ",
"ZEND_POST_DEC_OBJ ",
"ZEND_ASSIGN_OBJ ",
"ZEND_OP_DATA ",
"ZEND_INSTANCEOF ",
"ZEND_DECLARE_CLASS ",
"ZEND_DECLARE_INHERITED_CLASS ",
"ZEND_DECLARE_FUNCTION ",
"ZEND_RAISE_ABSTRACT_ERROR "
};
static DEZ_NODE_SPEC dez_node_specs[] =
{
{"", dez_node_cvt_nop, dez_node_output_nop, dez_node_free_nop}, /* DEZ_OP_NOP*/
{" + ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_ADD*/
{" - ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_SUB*/
{" * ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_MUL*/
{" / ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_DIV*/
{" % ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_MOD*/
{" << ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_SL*/
{" >> ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_SR*/
{".", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_CONCAT*/
{" | ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_BW_OR */
{" & ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_BW_AND*/
{" ^ ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_BW_XOR*/
{"~", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_BW_NOT*/
{"!", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_BOOL_NOT */
{" === ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_IS_IDENTICAL */
{" !== ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_IS_NOT_IDENTICAL */
{" == ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_IS_EQUAL */
{" != ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_IS_NOT_EQUAL */
{" < ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_IS_SMALLER*/
{" <= ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_IS_SMALLER_OR_EQUAL*/
{"(xxx)a", dez_node_cvt_expr, dez_node_output_cast, dez_node_free_expr}, /* DEZ_OP_CAST */
{"a?b:c", dez_node_cvt_qm_assign, dez_node_output_qm_assign, dez_node_free_expr}, /* DEZ_OP_QM_ASSIGN */
{" += ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_ASSIGN_ADD*/
{" -= ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_ASSIGN_SUB*/
{" *= ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_ASSIGN_MUL*/
{" /= ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_ASSIGN_DIV*/
{" %= ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_ASSIGN_MOD*/
{" <<= ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_ASSIGN_SL */
{" >>= ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_ASSIGN_SR */
{" .= ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_ASSIGN_CONCAT */
{" |= ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_ASSIGN_BW_OR */
{" &= ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_ASSIGN_BW_AND */
{" ^= ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_ASSIGN_BW_XOR */
{"++", dez_node_cvt_expr, dez_node_output_pre, dez_node_free_expr}, /* DEZ_OP_PRE_INC*/
{"--", dez_node_cvt_expr, dez_node_output_pre, dez_node_free_expr}, /* DEZ_OP_PRE_DEC*/
{"++", dez_node_cvt_expr, dez_node_output_post, dez_node_free_expr}, /* DEZ_OP_POST_INC */
{"--", dez_node_cvt_expr, dez_node_output_post, dez_node_free_expr}, /* DEZ_OP_POST_DEC */
{" = ", dez_node_cvt_expr, dez_node_output_assign, dez_node_free_expr}, /* DEZ_OP_ASSIGN*/
{" = &", dez_node_cvt_expr, dez_node_output_assign_ref, dez_node_free_expr}, /* DEZ_OP_ASSIGN_REF*/
{"echo ", dez_node_cvt_expr, dez_node_output_pre, dez_node_free_expr}, /* DEZ_OP_ECHO */
{"print ", dez_node_cvt_expr, dez_node_output_pre, dez_node_free_expr}, /* DEZ_OP_PRINT */
{"", dez_node_cvt_expr, dez_node_output_include_or_eval, dez_node_free_expr}, /* DEZ_OP_INCLUDE_OR_EVAL*/
{" OR ", dez_node_cvt_expr, dez_node_output_or_and, dez_node_free_expr}, /* DEZ_OP_LOGICAL_OR*/
{" XOR ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_LOGICAL_XOR*/
{" AND ", dez_node_cvt_expr, dez_node_output_or_and, dez_node_free_expr}, /* DEZ_OP_LOGICAL_AND*/
{"new ", dez_node_cvt_expr, dez_node_output_new, dez_node_free_expr}, /* DEZ_OP_NEW*/
{"exit", dez_node_cvt_expr, dez_node_output_exit, dez_node_free_expr}, /* DEZ_OP_EXIT */
{"if ", dez_node_cvt_if, dez_node_output_if, dez_node_free_if}, /* DEZ_OP_IF*/
{"elseif ", dez_node_cvt_unknown, dez_node_output_unknown, dez_node_free_unknown}, /* DEZ_OP_ELSEIF*/
{"else", dez_node_cvt_expr, dez_node_output_pre, dez_node_free_expr}, /* DEZ_OP_ELSE */
{"do", dez_node_cvt_do, dez_node_output_do, dez_node_free_expr}, /* DEZ_OP_DO*/
{"while ", dez_node_cvt_unknown, dez_node_output_if, dez_node_free_if}, /* DEZ_OP_WHILE */
{"for ", dez_node_cvt_for, dez_node_output_for, dez_node_free_for}, /* DEZ_OP_FOR*/
{"foreach ", dez_node_cvt_foreach, dez_node_output_foreach, dez_node_free_foreach}, /* DEZ_OP_FOREACH*/
{"declare ", dez_node_cvt_expr, dez_node_output_declare, dez_node_free_expr}, /* DEZ_OP_DECLARE*/
{"", dez_node_cvt_unknown, dez_node_output_pre, dez_node_free_expr}, /* DEZ_OP_AS*/
{"switch ", dez_node_cvt_unknown, dez_node_output_if, dez_node_free_if}, /* DEZ_OP_SWITCH*/
{"case ", dez_node_cvt_case, dez_node_output_case, dez_node_free_case}, /* DEZ_OP_CASE */
{"default:", dez_node_cvt_default, dez_node_output_default, dez_node_free_default}, /* DEZ_OP_DEFAULT*/
{"break", dez_node_cvt_expr, dez_node_output_pre2, dez_node_free_expr}, /* DEZ_OP_BREAK */
{"continue", dez_node_cvt_expr, dez_node_output_pre2, dez_node_free_expr}, /* DEZ_OP_CONTINUE */
{"old_function", dez_node_cvt_unknown, dez_node_output_unknown, dez_node_free_unknown}, /* DEZ_OP_OLD_FUNCTION */
{"function ", dez_node_cvt_function_or_class, dez_node_output_function, dez_node_free_function}, /* DEZ_OP_FUNCTION */
{"const", dez_node_cvt_unknown, dez_node_output_unknown, dez_node_free_unknown}, /* DEZ_OP_CONST */
{"return ", dez_node_cvt_expr, dez_node_output_pre, dez_node_free_expr}, /* DEZ_OP_RETURN*/
{"use", dez_node_cvt_unknown, dez_node_output_unknown, dez_node_free_unknown}, /* DEZ_OP_USE*/
{"var ", dez_node_cvt_unknown, dez_node_output_var, dez_node_free_var}, /* DEZ_OP_VAR*/
{"unset ", dez_node_cvt_expr, dez_node_output_unset, dez_node_free_expr}, /* DEZ_OP_UNSET */
{"isset ", dez_node_cvt_expr, dez_node_output_isset_or_empty, dez_node_free_expr}, /* DEZ_OP_ISSET */
{"empty ", dez_node_cvt_unknown, dez_node_output_unknown, dez_node_free_unknown}, /* DEZ_OP_EMPTY */
{"class ", dez_node_cvt_function_or_class, dez_node_output_class, dez_node_free_class}, /* DEZ_OP_CLASS */
{"extends", dez_node_cvt_unknown, dez_node_output_unknown, dez_node_free_unknown}, /* DEZ_OP_EXTENDS*/
{"->", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr}, /* DEZ_OP_OBJECT_OPERATOR*/
{" => ", dez_node_cvt_double_arrow, dez_node_output_double_arrow, dez_node_free_da}, /* DEZ_OP_DOUBLE_ARROW */
{"list ", dez_node_cvt_unknown, dez_node_output_list, dez_node_free_list}, /* DEZ_OP_LIST */
{"array ", dez_node_cvt_array, dez_node_output_array, dez_node_free_da}, /* DEZ_OP_ARRAY */
{"__CLASS__", dez_node_cvt_unknown, dez_node_output_unknown, dez_node_free_unknown}, /* DEZ_OP_CLASS_C*/
{"__FUNCTION__", dez_node_cvt_unknown, dez_node_output_unknown, dez_node_free_unknown}, /* DEZ_OP_FUNC_C*/
{"__LINE__", dez_node_cvt_unknown, dez_node_output_unknown, dez_node_free_unknown}, /* DEZ_OP_LINE */
{"__FILE__", dez_node_cvt_unknown, dez_node_output_unknown, dez_node_free_unknown}, /* DEZ_OP_FILE */
{"", dez_node_cvt_unknown, dez_node_output_unknown, dez_node_free_unknown}, /* DEZ_OP_COMMENT*/
/****/ {"<<<", dez_node_cvt_heredoc, dez_node_output_heredoc, dez_node_free_heredoc}, /* DEZ_OP_HEREDOC*/
/****/ {"", dez_node_cvt_dollar_open_curly_braces, dez_node_output_dollar_open_curly_braces, dez_node_free_dollar_open_curly_braces},/* DEZ_OP_DOLLAR_OPEN_CURLY_BRACES */
{"::", dez_node_cvt_unknown, dez_node_output_unknown, dez_node_free_unknown}, /* DEZ_OP_PAAMAYIM_NEKUDOTAYIM */
{"", dez_node_cvt_expr, dez_node_output_call_param, dez_node_free_expr}, /* DEZ_OP_CALL_PARAM */
{"", dez_node_cvt_expr, dez_node_output_call_init, dez_node_free_expr}, /* DEZ_OP_CALL_INIT */
{"", dez_node_cvt_call, dez_node_output_call, dez_node_free_expr}, /* DEZ_OP_CALL */
{"", dez_node_cvt_call, dez_node_output_call_ex, dez_node_free_expr}, /* DEZ_OP_CALL_EX */
{"", dez_node_cvt_bool, dez_node_output_unknown, dez_node_free_expr}, /* DEZ_OP_BOOL */
{"a[b]", dez_node_cvt_expr, dez_node_output_fetch_dim, dez_node_free_expr}, /* DEZ_OP_FETCH_DIM */
{"''", dez_node_cvt_expr, dez_node_output_init_string, dez_node_free_expr}, /* DEZ_OP_INIT_STRING */
{"$", dez_node_cvt_expr, dez_node_output_pre, dez_node_free_expr}, /* DEZ_OP_FETCH */
{"", dez_node_cvt_expr, dez_node_output_fetch_constant, dez_node_free_expr}, /* DEZ_OP_FETCH_CONSTANT */
{"jmp", dez_node_cvt_jmp, dez_node_output_pre, dez_node_free_if}, /* DEZ_OP_JMP */
{"", dez_node_cvt_func_param, dez_node_output_func_param, dez_node_free_expr}, /* DEZ_OP_FUNC_PARAM */
{"@", dez_node_cvt_expr, dez_node_output_unknown, dez_node_free_expr}, /* DEZ_OP_BEGIN_SILENCE */
{"", dez_node_cvt_expr, dez_node_output_unknown, dez_node_free_expr}, /* DEZ_OP_END_SILENCE */
{"", dez_node_cvt_unknown, dez_node_output_le, dez_node_free_le}, /* DEZ_OP_END_SILENCE */
{"", dez_node_cvt_unknown, dez_node_output_unknown, dez_node_free_unknown} /* DEZ_OP_UNKNOWN */
};
static DEZ_OP_TYPE dez_op_types[] =
{
{DEZ_OP_NOP , 1, {ZEND_NOP}},
{DEZ_OP_NOP , 1, {ZEND_FREE}},
{DEZ_OP_NOP , 1, {ZEND_SWITCH_FREE}},
{DEZ_OP_NOP , 1, {ZEND_INIT_CTOR_CALL}},
{DEZ_OP_ADD , 1, {ZEND_ADD}},
{DEZ_OP_SUB , 1, {ZEND_SUB}},
{DEZ_OP_MUL , 1, {ZEND_MUL}},
{DEZ_OP_DIV , 1, {ZEND_DIV}},
{DEZ_OP_MOD , 1, {ZEND_MOD}},
{DEZ_OP_SL , 1, {ZEND_SL}},
{DEZ_OP_SR , 1, {ZEND_SR}},
{DEZ_OP_CONCAT , 1, {ZEND_CONCAT}},
{DEZ_OP_CONCAT , 1, {ZEND_ADD_STRING}},
{DEZ_OP_CONCAT , 1, {ZEND_ADD_VAR}},
{DEZ_OP_CONCAT , 1, {ZEND_ADD_CHAR}},
{DEZ_OP_BW_OR , 1, {ZEND_BW_OR}},
{DEZ_OP_BW_AND , 1, {ZEND_BW_AND}},
{DEZ_OP_BW_XOR , 1, {ZEND_BW_XOR}},
{DEZ_OP_BW_NOT , 1, {ZEND_BW_NOT}},
{DEZ_OP_BOOL_NOT , 1, {ZEND_BOOL_NOT}},
{DEZ_OP_IS_IDENTICAL , 1, {ZEND_IS_IDENTICAL}},
{DEZ_OP_IS_NOT_IDENTICAL , 1, {ZEND_IS_NOT_IDENTICAL}},
{DEZ_OP_IS_EQUAL , 1, {ZEND_IS_EQUAL}},
{DEZ_OP_IS_NOT_EQUAL , 1, {ZEND_IS_NOT_EQUAL}},
{DEZ_OP_IS_SMALLER , 1, {ZEND_IS_SMALLER}},
{DEZ_OP_IS_SMALLER_OR_EQUAL , 1, {ZEND_IS_SMALLER_OR_EQUAL}},
{DEZ_OP_CAST , 1, {ZEND_CAST}},
{DEZ_OP_QM_ASSIGN , 2, {ZEND_QM_ASSIGN, ZEND_JMP}},
{DEZ_OP_QM_ASSIGN , 1, {ZEND_QM_ASSIGN}},
{DEZ_OP_ASSIGN_ADD , 1, {ZEND_ASSIGN_ADD}},
{DEZ_OP_ASSIGN_SUB , 1, {ZEND_ASSIGN_SUB}},
{DEZ_OP_ASSIGN_MUL , 1, {ZEND_ASSIGN_MUL}},
{DEZ_OP_ASSIGN_DIV , 1, {ZEND_ASSIGN_DIV}},
{DEZ_OP_ASSIGN_MOD , 1, {ZEND_ASSIGN_MOD}},
{DEZ_OP_ASSIGN_SL , 1, {ZEND_ASSIGN_SL}},
{DEZ_OP_ASSIGN_SR , 1, {ZEND_ASSIGN_SR}},
{DEZ_OP_ASSIGN_CONCAT , 1, {ZEND_ASSIGN_CONCAT}},
{DEZ_OP_ASSIGN_BW_OR , 1, {ZEND_ASSIGN_BW_OR}},
{DEZ_OP_ASSIGN_BW_AND , 1, {ZEND_ASSIGN_BW_AND}},
{DEZ_OP_ASSIGN_BW_XOR , 1, {ZEND_ASSIGN_BW_XOR}},
{DEZ_OP_PRE_INC , 1, {ZEND_PRE_INC}},
{DEZ_OP_PRE_DEC , 1, {ZEND_PRE_DEC}},
{DEZ_OP_POST_INC , 1, {ZEND_POST_INC}},
{DEZ_OP_POST_DEC , 1, {ZEND_POST_DEC}},
{DEZ_OP_ASSIGN , 1, {ZEND_ASSIGN}},
{DEZ_OP_ASSIGN_REF , 1, {ZEND_ASSIGN_REF}},
{DEZ_OP_ECHO , 1, {ZEND_ECHO}},
{DEZ_OP_PRINT , 1, {ZEND_PRINT}},
{DEZ_OP_INCLUDE_OR_EVAL , 1, {ZEND_INCLUDE_OR_EVAL}},
{DEZ_OP_LOGICAL_OR , 1, {ZEND_JMPNZ_EX}},
{DEZ_OP_LOGICAL_XOR , 1, {ZEND_BOOL_XOR}},
{DEZ_OP_LOGICAL_AND , 1, {ZEND_JMPZ_EX}},
{DEZ_OP_NEW , 3, {ZEND_NEW, ZEND_JMP_NO_CTOR, ZEND_INIT_FCALL_BY_NAME}},
{DEZ_OP_NEW , 3, {ZEND_NEW, ZEND_JMP, ZEND_INIT_FCALL_BY_NAME}},
{DEZ_OP_NEW , 2, {ZEND_NEW, ZEND_INIT_FCALL_BY_NAME}},
{DEZ_OP_EXIT , 1, {ZEND_EXIT}},
{DEZ_OP_IF , 1, {ZEND_JMPZ}},
// {DEZ_OP_ELSEIF , 1, {???ZEND_JMPZ}},
// {DEZ_OP_ELSE , 1, {ZEND_JMP}},
{DEZ_OP_DO , 1, {ZEND_JMPNZ}},
// {DEZ_OP_WHILE , 1, {???ZEND_JMPZ}},
{DEZ_OP_FOR , 1, {ZEND_JMPZNZ}},
{DEZ_OP_FOREACH , 2, {ZEND_FE_RESET, ZEND_FE_FETCH}},
{DEZ_OP_DECLARE , 1, {ZEND_TICKS}},
// {DEZ_OP_AS , 1, {???}},
// {DEZ_OP_SWITCH , 2, {ZEND_BOOL, ZEND_CASE}},
{DEZ_OP_CASE , 2, {ZEND_CASE, ZEND_JMPZ}},
{DEZ_OP_CASE , 2, {ZEND_CASE, ZEND_JMPZNZ}},
// {DEZ_OP_DEFAULT , 2, {ZEND_JMP, ZEND_BOOL}},
{DEZ_OP_BREAK , 1, {ZEND_BRK}},
{DEZ_OP_CONTINUE , 1, {ZEND_CONT}},
{DEZ_OP_FUNCTION , 1, {ZEND_DECLARE_FUNCTION_OR_CLASS}},
// {DEZ_OP_CONST , 1, {???}},
{DEZ_OP_RETURN , 1, {ZEND_RETURN}},
// {DEZ_OP_VAR , 1, {???}},
{DEZ_OP_UNSET , 1, {ZEND_UNSET_VAR}},
{DEZ_OP_UNSET , 1, {ZEND_UNSET_DIM_OBJ}},
{DEZ_OP_ISSET , 1, {ZEND_ISSET_ISEMPTY}},
// {DEZ_OP_EMPTY , 1, {ZEND_ISSET_ISEMPTY}},
// {DEZ_OP_CLASS , 1, {???ZEND_DECLARE_FUNCTION_OR_CLASS}},
// {DEZ_OP_EXTENDS , 1, {???}},
{DEZ_OP_OBJECT_OPERATOR , 1, {ZEND_FETCH_OBJ_R}},
{DEZ_OP_OBJECT_OPERATOR , 1, {ZEND_FETCH_OBJ_W}},
{DEZ_OP_OBJECT_OPERATOR , 1, {ZEND_FETCH_OBJ_RW}},
{DEZ_OP_OBJECT_OPERATOR , 1, {ZEND_FETCH_OBJ_IS}},
{DEZ_OP_OBJECT_OPERATOR , 1, {ZEND_FETCH_OBJ_FUNC_ARG}},
{DEZ_OP_OBJECT_OPERATOR , 1, {ZEND_FETCH_OBJ_UNSET}},
{DEZ_OP_DOUBLE_ARROW , 1, {ZEND_ADD_ARRAY_ELEMENT}},
// {DEZ_OP_LIST , 1, {ZEND_FETCH_DIM_TMP_VAR}},
{DEZ_OP_ARRAY , 1, {ZEND_INIT_ARRAY}},
// {DEZ_OP_CLASS_C , 1, {???}},
// {DEZ_OP_FUNC_C , 1, {???}},
// {DEZ_OP_LINE , 1, {???}},
// {DEZ_OP_FILE , 1, {???}},
// {DEZ_OP_COMMENT , 1, {???}},
// {DEZ_OP_HEREDOC , 1, {???}},
// {DEZ_OP_DOLLAR_OPEN_CURLY_BRACES, 1, {???}},
// {DEZ_OP_PAAMAYIM_NEKUDOTAYIM , 1, {???ZEND_INIT_FCALL_BY_NAME}},
{DEZ_OP_CALL_PARAM , 1, {ZEND_SEND_VAL}},
{DEZ_OP_CALL_PARAM , 1, {ZEND_SEND_VAR}},
{DEZ_OP_CALL_PARAM , 1, {ZEND_SEND_REF}},
{DEZ_OP_CALL_PARAM , 1, {ZEND_SEND_VAR_NO_REF}},
{DEZ_OP_CALL_INIT , 1, {ZEND_INIT_FCALL_BY_NAME}},
{DEZ_OP_CALL , 1, {ZEND_DO_FCALL}},
{DEZ_OP_CALL , 1, {ZEND_DO_FCALL_BY_NAME}},
{DEZ_OP_CALL_EX , 1, {ZEND_CLONE}},
{DEZ_OP_BOOL , 1, {ZEND_BOOL}},
{DEZ_OP_FETCH_DIM , 1, {ZEND_FETCH_DIM_W}},
{DEZ_OP_FETCH_DIM , 1, {ZEND_FETCH_DIM_R}},
{DEZ_OP_FETCH_DIM , 1, {ZEND_FETCH_DIM_RW}},
{DEZ_OP_FETCH_DIM , 1, {ZEND_FETCH_DIM_IS}},
{DEZ_OP_FETCH_DIM , 1, {ZEND_FETCH_DIM_TMP_VAR}},
{DEZ_OP_FETCH_DIM , 1, {ZEND_FETCH_DIM_FUNC_ARG}},
{DEZ_OP_FETCH_DIM , 1, {ZEND_FETCH_DIM_UNSET}},
{DEZ_OP_INIT_STRING , 1, {ZEND_INIT_STRING}},
{DEZ_OP_FETCH , 1, {ZEND_FETCH_W}},
{DEZ_OP_FETCH , 1, {ZEND_FETCH_R}},
{DEZ_OP_FETCH , 1, {ZEND_FETCH_RW}},
{DEZ_OP_FETCH , 1, {ZEND_FETCH_IS}},
{DEZ_OP_FETCH , 1, {ZEND_FETCH_FUNC_ARG}},
{DEZ_OP_FETCH , 1, {ZEND_FETCH_UNSET}},
{DEZ_OP_FETCH_CONSTANT , 1, {ZEND_FETCH_CONSTANT}},
{DEZ_OP_FUNC_PARAM , 1, {ZEND_RECV}},
{DEZ_OP_FUNC_PARAM , 1, {ZEND_RECV_INIT}},
{DEZ_OP_BEGIN_SILENCE , 1, {ZEND_BEGIN_SILENCE}},
{DEZ_OP_END_SILENCE , 1, {ZEND_END_SILENCE}},
{DEZ_OP_JMP , 1, {ZEND_JMP}}
};
static unsigned char m_opc_stack[OPC_STACK_SIZE];
static zend_op *m_op_buffer[OPC_STACK_SIZE];
static int m_opc_num = 0;
static DEZ_NODE *m_node_stack[NODE_STACK_SIZE];
static int m_node_num = 0;
static DEZ_NODE *m_dez_op_root = NULL; /* pointer to the root of dez ops */
static DEZ_NODE *m_dez_op_prev = NULL; /* pointer to the previous dez op */
static DEZ_NODE *m_dez_op_current = NULL; /* pointer to the current dez op */
static zend_op *m_zend_op_start = NULL; /* pointer to the start of zend ops */
static zend_op *m_zend_op_end = NULL; /* pointer to the end of zend ops */
static zend_op *m_zend_op_current = NULL; /* pointer to the current zend op */
static short m_zend_op_match_n = 0; /* the number of matching zend op */
static DEZ_ZEND_OP_DUP m_zend_op_dup[512]; /* the duplicate zend op */
static int m_zend_op_dup_num = 0;
static int m_max_jmp_dest = 0;
static DEZ_NODE *m_current_function = NULL; /* pointer to current function node */
static DEZ_BRK_CNT_NODE *m_dez_brk_cnt_root = NULL; /* pointer to the root of break/continue node */
static DEZ_BRK_CNT_NODE *m_dez_brk_cnt_tail = NULL; /* pointer to the tailer of break/continue node */
static int dez_opc_push(zend_op *pzop)
{
if (m_opc_num >= OPC_STACK_SIZE) /* the stack is full */
{
return -1;
}
m_opc_stack[m_opc_num] = (unsigned char)(pzop->opcode);
m_op_buffer[m_opc_num++] = pzop;
return 0;
}
static void dez_opc_pop(int n)
{
if (n > m_opc_num)
{
n = m_opc_num;
}
m_opc_num -= n;
if (m_opc_num > 0)
{
memmove (m_opc_stack, m_opc_stack + m_opc_num, n*sizeof(m_opc_stack[0]));
memmove (m_op_buffer, m_op_buffer + m_opc_num, n*sizeof(m_op_buffer[0]));
}
}
static void dez_opc_refresh(void)
{
int i = 0;
while(i < m_opc_num)
{
m_opc_stack[i] = m_op_buffer[i]->opcode;
i++;
}
}
/* return: <0: error; 0: need to continue; 1: not matching; 2: matching */
static int dez_opc_compare(const unsigned char *opcs, int len)
{
int i;
int r;
if (len > m_opc_num)
{
len = m_opc_num;
r = 0;
}
else
{
r = 2;
}
for (i = 0; i < len; i++)
{
if (m_opc_stack[i] != opcs[i]) /* not matching */
{
return 1;
}
}
return r;
}
static int dez_node_push(DEZ_NODE *node)
{
if (m_node_num >= NODE_STACK_SIZE) /* the stack is full */
{
return -1;
}
m_node_stack[m_node_num++] = node;
return 0;
}
static DEZ_NODE *dez_node_pop()
{
if (m_node_num <= 0) /* the stack is empty */
{
return NULL;
}
return m_node_stack[--m_node_num];
}
static DEZ_NODE *dez_node_get()
{
if (m_node_num <= 0) /* the stack is empty */
{
return NULL;
}
return m_node_stack[m_node_num-1];
}
static DEZ_BRK_CNT_NODE *dez_brk_cnt_add(const DEZ_NODE *node)
{
DEZ_BRK_CNT_NODE *pbrk_cnt;
if (node == NULL)
{
return NULL;
}
pbrk_cnt = (DEZ_BRK_CNT_NODE *)malloc(sizeof(DEZ_BRK_CNT_NODE));
if (pbrk_cnt == NULL)
{
return NULL;
}
pbrk_cnt->node = node;
pbrk_cnt->next = NULL;
if (m_dez_brk_cnt_root == NULL) /* no break/continue node */
{
pbrk_cnt->prev = NULL;
m_dez_brk_cnt_root = pbrk_cnt;
m_dez_brk_cnt_tail = pbrk_cnt;
}
else
{
pbrk_cnt->prev = m_dez_brk_cnt_tail;
m_dez_brk_cnt_tail->next = pbrk_cnt;
m_dez_brk_cnt_tail = pbrk_cnt;
}
return pbrk_cnt;
}
static int dez_brk_cnt_del(DEZ_BRK_CNT_NODE *pbrk_cnt)
{
if (pbrk_cnt == NULL)
{
return -1;
}
if (pbrk_cnt->prev != NULL)
{
pbrk_cnt->prev->next = pbrk_cnt->next;
}
else /* the root */
{
m_dez_brk_cnt_root = pbrk_cnt->next;
}
if (pbrk_cnt->next != NULL)
{
pbrk_cnt->next->prev = pbrk_cnt->prev;
}
else /* the tailer */
{
m_dez_brk_cnt_tail = pbrk_cnt->prev;
}
free(pbrk_cnt);
return 0;
}
static int dez_brk_cnt_del_to_tail(DEZ_BRK_CNT_NODE *pbrk_cnt)
{
if (pbrk_cnt == NULL)
{
return -1;
}
if (pbrk_cnt->prev != NULL)
{
pbrk_cnt->prev->next = pbrk_cnt->next;
}
else /* the root */
{
m_dez_brk_cnt_root = NULL;
}
m_dez_brk_cnt_tail = pbrk_cnt->prev;
while(pbrk_cnt != NULL)
{
DEZ_BRK_CNT_NODE *pnext = pbrk_cnt->next;
free(pbrk_cnt);
pbrk_cnt = pnext;
}
return 0;
}
static int dez_brk_cnt_del_by_node(const DEZ_NODE *node)
{
DEZ_NODE_EXPR *content;
DEZ_BRK_CNT_NODE *p;
if (node == NULL)
{
return -1;
}
content = (DEZ_NODE_EXPR *)(node->content);
if (content != NULL && content->branch_node != NULL)
{
DEZ_NODE *sub;
sub = content->branch_node->next;
while(sub != NULL)
{
dez_brk_cnt_del_by_node(sub);
sub = sub->next;
}
}
p = m_dez_brk_cnt_root;
while (p != NULL)
{
if (p->node == node)
{
dez_brk_cnt_del(p);
return 0;
}
p = p->next;
}
return -1;
}
static int dez_brk_cnt_free(void)
{
DEZ_BRK_CNT_NODE *p = m_dez_brk_cnt_root;
while(p != NULL)
{
DEZ_BRK_CNT_NODE *next = p->next;
free(p);
p = next;
}
m_dez_brk_cnt_root = NULL;
m_dez_brk_cnt_tail = NULL;
return 0;
}
static inline zend_op *ZEND_GET_ORI(zend_op *x)
{
if (x >= (zend_op *)m_zend_op_dup && x < (zend_op *)(m_zend_op_dup+m_zend_op_dup_num))
{
return m_zend_op_start + *((int *)((x)+1));
}
else
{
return x;
}
}
static int dez_add_var (int index, char *name, int namelen)
{
DEZ_VAR *m_vars;
int *m_var_num;
if (m_current_function == NULL) /* global source */
{
m_vars = m_dez_vars;
m_var_num = &m_dez_var_num;
}
else /* in function */
{
DEZ_NODE_FUNCTION *fc = (DEZ_NODE_FUNCTION *)(m_current_function->content);
m_vars = fc->m_dez_vars;
m_var_num = &(fc->m_dez_var_num);
}
if (*m_var_num >= DEZ_VARS_NUM)
{
return -1;
}
if (namelen >= sizeof(m_vars[0].varname) - 2)
{
namelen = sizeof(m_vars[0].varname) - 3;
}
m_vars[*m_var_num].index = index;
m_vars[*m_var_num].varname[0] = '$';
memcpy(m_vars[*m_var_num].varname+1, name, namelen);
m_vars[*m_var_num].varname[namelen+1] = '\0';
(*m_var_num)++;
return 0;
}
static char *dez_get_varname(znode *zn)
{
static DEZ_EG_RESERVED *pegr;
static DEZ_EG_VAR_NAME *vars;
static char str[1024];
int i;
DEZ_VAR *m_vars;
int *m_var_num;
TSRMLS_FETCH();
if (m_current_function == NULL) /* global source */
{
m_vars = m_dez_vars;
m_var_num = &m_dez_var_num;
vars = NULL;
if (EG(active_op_array)->reserved[0] != NULL)
{
vars = ((DEZ_EG_RESERVED *)(EG(active_op_array)->reserved[0]))->vars;
}
}
else /* in function */
{
DEZ_NODE_FUNCTION *fc = (DEZ_NODE_FUNCTION *)(m_current_function->content);
m_vars = fc->m_dez_vars;
m_var_num = &(fc->m_dez_var_num);
vars = NULL;
if (fc->op_array->reserved[0] != NULL)
{
pegr = (DEZ_EG_RESERVED *)(fc->op_array->reserved[0]);
vars = ((DEZ_EG_RESERVED *)(fc->op_array->reserved[0]))->vars;
}
}
for (i = 0; i < *m_var_num; i++)
{
if (m_vars[i].index == zn->u.var)
{
return m_vars[i].varname;
}
}
if (vars != NULL)
{
sprintf (str, "$%s", vars[zn->u.var].var);
return str;
}
sprintf (str, "$dez_var_%d", zn->u.var);
return str;
}
static void dez_prep_zend_op(zend_op *ops, int n)
{
static unsigned char *m_zop2op = NULL;
static int m_init = 0;
DEZ_EG_E *pe;
TSRMLS_FETCH();
int i;
if (m_init == 0)
{
m_init = 1;
if (EG(active_op_array)->reserved[0] != NULL)
{
pe = ((DEZ_EG_RESERVED *)(EG(active_op_array)->reserved[0]))->e;
if (pe != NULL)
{
m_zop2op = pe->zop2op;
}
}
}
if (m_zop2op != NULL)
{
i = 0;
while(i < n)
{
ops[i].opcode = m_zop2op[ops[i].opcode] - (i%8);
i++;
}
}
}
inline char *dez_get_funcname(znode *zn)
{
static char str[1024];
static DEZ_EG_FUNC *funcs0;
static DEZ_EG_FUNC_NAME *funcs;
TSRMLS_FETCH();
if (m_current_function == NULL) /* global source */
{
funcs0 = NULL;
funcs = NULL;
if (EG(active_op_array)->reserved[0] != NULL)
{
funcs0 = ((DEZ_EG_RESERVED *)(EG(active_op_array)->reserved[0]))->funcs;
if (funcs0 != NULL)
{
funcs = funcs0->funcs;
}
}
}
else /* in function */
{
DEZ_NODE_FUNCTION *fc = (DEZ_NODE_FUNCTION *)(m_current_function->content);
funcs0 = NULL;
funcs = NULL;
if (fc->op_array->reserved[0] != NULL)
{
funcs0 = ((DEZ_EG_RESERVED *)(fc->op_array->reserved[0]))->funcs;
if (funcs0 != NULL)
{
funcs = funcs0->funcs;
}
}
}
if (funcs != NULL)
{
return funcs[zn->u.var].func;
}
sprintf (str, "dez_func_%d", zn->u.var);
return str;
}
inline void dez_dump_zval_null(zvalue_value value)
{
printf ( "null");
}
inline void dez_dump_zval_long(zvalue_value value)
{
printf ( "%ld", value.lval);
}
inline void dez_dump_zval_double(zvalue_value value)
{
printf ( "%g", value.dval);
}
static void dez_dump_zval (zval val, int isstr);
inline void dez_dump_zval_string(zvalue_value value, int isstr)
{
static char buff[2*1024];
char *new_str,*p1, *p2;
int new_len;
zval zv;
if (isstr != 0)
{
if (strlen(value.str.val)*2 < sizeof(buff))
{
new_str = buff;
}
else
{
new_str = (char *)malloc(strlen(value.str.val)*2+1);
if (new_str == NULL)
{
new_str = buff;
}
}
p1 = value.str.val;
p2 = new_str;
while(*p1 != '\0')
{
if (
*p1 == '\'' ||
*p1 == '\\'
)
{
(*p2++) = '\\';
}
(*p2++) = (*p1++);
}
*p2 = '\0';
#if 0
if (zend_get_constant(value.str.val, value.str.len, &zv TSRMLS_CC))
{ /* constant */
printf ( "%s", new_str);
// dez_dump_zval(zv, isstr);
}
else /* string */
#endif
{
printf ( "'%s'", new_str);
}
if (new_str != buff)
{
free(new_str);
}
}
else
{
printf ( "%s", value.str.val);
}
// efree(new_str);
}
inline void dez_dump_zval_array(zvalue_value value)
{
printf ( "<array>");
}
static void dez_dump_zval (zval val, int isstr);
static void dez_dump_static_array_elements (HashTable *ht)
{
if (ht != NULL)
{
Bucket *p = ht->pListHead;
printf ("array (");
while(p != NULL && p->pData != NULL)
{
zval *value;
if (p->nKeyLength == 0) /* key is LONG or no key */
{
printf ("%u => ", p->h);
}
else /* key is STRING */
{
printf ("'%s' => ", (char *)(p->arKey));
}
value = *((zval **)(p->pData));
if (value != NULL)
{
dez_dump_zval(*value, 1);
}
p = p->pListNext;
if (p != NULL)
{
printf (", ");
}
}
printf (")");
}
}
inline void dez_dump_zval_object(zvalue_value value)
{
printf ( "<object>");
}
inline void dez_dump_zval_bool(zvalue_value value)
{
printf ( value.lval ? "true" : "false");
}
inline void dez_dump_zval_resource(zvalue_value value)
{
printf ( "<resource>");
}
inline void dez_dump_zval_constant(zvalue_value value)
{
printf ( "%s", value.str.val);
}
inline void dez_dump_zval_constant_array(zvalue_value value)
{
// printf ( "<const array>");
dez_dump_static_array_elements(value.ht);
}
static zend_op *dez_dup_zend_op(const zend_op *zop)
{
zend_op *newzop = &(m_zend_op_dup[m_zend_op_dup_num].zop);
memcpy(newzop, zop, sizeof(zend_op));
m_zend_op_dup[m_zend_op_dup_num++].linenum = ZEND_LINENUM(zop);
return newzop;
}
/* recover = 0: clear; = 1: recover */
void clear_or_recover_zend_op(zend_op *start, int num, int recover)
{
struct DEL_ZEND_OP
{
int linenum;
unsigned char opcode;
};
static struct DEL_ZEND_OP m_del_zendop[1024];
static int m_del_zendop_num = 0;
if (start == NULL) /* clear buffer */
{
m_del_zendop_num = 0;
}
if (recover == 0) /* clear */
{
int start_linenum = ZEND_LINENUM(start);
if (
m_max_jmp_dest >= start_linenum &&
m_max_jmp_dest < start_linenum+num
) /* the dest of jmp is in the range of clean */
{
num = m_max_jmp_dest - start_linenum;
}
while(num > 0 && start < m_zend_op_end)
{
m_del_zendop[m_del_zendop_num].linenum = ZEND_LINENUM(start);
m_del_zendop[m_del_zendop_num].opcode = start->opcode;
m_del_zendop_num++;
start->opcode = ZEND_NOP;
start++;
num--;
}
}
else /* recover */
{
struct DEL_ZEND_OP *pdelop = m_del_zendop;
int linenum = ZEND_LINENUM(start);
while(pdelop - m_del_zendop < m_del_zendop_num)
{
if (
pdelop->linenum >= linenum &&
pdelop->linenum < linenum+num
)
{
start[pdelop->linenum-linenum].opcode = pdelop->opcode;
}
pdelop++;
}
}
}
static void dez_dump_zval (zval val, int isstr)
{
switch (val.type) {
case IS_NULL: dez_dump_zval_null (val.value); break;
case IS_LONG: dez_dump_zval_long (val.value); break;
case IS_DOUBLE: dez_dump_zval_double (val.value); break;
case IS_STRING: dez_dump_zval_string (val.value, isstr); break;
case IS_ARRAY: dez_dump_zval_array (val.value); break;
case IS_OBJECT: dez_dump_zval_object (val.value); break;
case IS_BOOL: dez_dump_zval_bool (val.value); break;
case IS_RESOURCE: dez_dump_zval_resource (val.value); break;
case IS_CONSTANT: dez_dump_zval_constant (val.value); break;
case IS_CONSTANT_ARRAY: dez_dump_zval_constant_array (val.value); break;
}
}
static void dez_dump_znode (znode *zn, int isstr)
{
switch(zn->op_type)
{
case IS_CONST:
dez_dump_zval (zn->u.constant, isstr);
break;
case 16:
printf ("%s", dez_get_varname(zn));
break;
}
}
static void dez_dump_znode_ex (znode *zn, int isstr)
{
switch(zn->op_type)
{
case IS_CONST:
dez_dump_zval (zn->u.constant, isstr);
break;
case IS_TMP_VAR:
printf ( "~%u", zn->u.constant.value.lval);
break;
case IS_VAR:
printf ( "$%u", zn->u.constant.value.lval);
break;
case 16:
// dez_dump_zval (zn->u.constant);
printf ("%s", dez_get_varname(zn));
break;
default:
printf ( "->%u", zn->u.constant.value.lval);
}
}
static int dez_branch_is_null (DEZ_NODE *node)
{
DEZ_NODE *branch;
if (node->content == NULL)
{
return 0;
}
branch = ((DEZ_NODE_EXPR *)(node->content))->branch_node;
while (branch != NULL)
{
if (branch->dez_op != DEZ_OP_NOP)
{
return -1;
}
branch = branch->next;
}
return 0;
}
static DEZ_NODE *dez_get_last_sub_node (DEZ_NODE *parent)
{
DEZ_NODE *node;
if (
parent == NULL ||
parent->content == NULL
)
{
return NULL;
}
if (dez_branch_is_null(parent) == 0) /* the branch is empty */
{
return NULL;
}
node = ((DEZ_NODE_EXPR *)(parent->content))->branch_node;
if (node == NULL)
{
return NULL;
}
while (node->next != NULL)
{
node = node->next;
}
return node;
}
static int get_zend_linenum (DEZ_NODE *node)
{
if (node == NULL)
{
return -1;
}
if (node->zop == NULL)
{
return -1;
}
if (
node->dez_op == DEZ_OP_FUNCTION ||
node->dez_op == DEZ_OP_CLASS
)
{
return -1;
}
else if (node->dez_op == DEZ_OP_FOR)
{
DEZ_NODE_FOR *content = (DEZ_NODE_FOR *)(node->content);
if (content != NULL)
{
if (content->after_node != NULL)
{
return ZEND_LINENUM(content->after_node->zop)+1;
}
}
}
else if (node->dez_op == DEZ_OP_FOREACH)
{
DEZ_NODE_FOREACH *content = (DEZ_NODE_FOREACH *)(node->content);
if (content == NULL)
{
return ZEND_LINENUM(node->zop)+1;
}
if (content->key_node != NULL)
{
if (ZEND_GET_ORI(content->key_node->zop)[1].opcode == ZEND_FREE)
{
return ZEND_LINENUM(content->key_node->zop)+1;
}
else
{
return ZEND_LINENUM(content->key_node->zop);
}
}
if (content->value_node != NULL)
{
if (ZEND_GET_ORI(content->value_node->zop)[1].opcode == ZEND_FREE)
{
return ZEND_LINENUM(content->value_node->zop)+1;
}
else
{
return ZEND_LINENUM(content->value_node->zop);
}
}
return ZEND_LINENUM(node->zop)+1;
}
return ZEND_LINENUM(node->zop);
}
static DEZ_NODE *get_parent_node(DEZ_NODE *node)
{
DEZ_NODE *parent, *p = node;
int i;
if (p == NULL)
{
return NULL;
}
while (p->prev != NULL)
{
p = p->prev;
}
for (i = m_node_num-1; i >= 0; i--)
{
parent = m_node_stack[i];
if (((DEZ_NODE_EXPR *)(parent->content))->branch_node == p)
{
return parent;
}
}
return NULL;
}
static int get_prev_zend_linenum (DEZ_NODE *node)
{
DEZ_NODE *prev, *next, *sub, *p = node;
if (p == NULL)
{
return -1;
}
next = node;
prev = p->prev;
while (prev != NULL)
{
if (
prev->dez_op == DEZ_OP_FUNCTION ||
prev->dez_op == DEZ_OP_CLASS
)
{
return -1;
}
else if (prev->dez_op != DEZ_OP_NOP)
{
break;
}
next = prev;
prev = prev->prev;
}
if (prev == NULL)
{
int i;
for (i = m_node_num-1; i >= 0; i--)
{
prev = m_node_stack[i];
if (((DEZ_NODE_EXPR *)(prev->content))->branch_node == next)
{
break;
}
}
if (i < 0) /* no parent */
{
return -1;
}
if (
prev->dez_op == DEZ_OP_DO || /* do{...}while() */
prev->dez_op == DEZ_OP_WHILE && prev->zop->opcode == ZEND_JMP /* while(true) */
)
{
return get_prev_zend_linenum(prev);
}
else
{
return get_zend_linenum(prev);
}
}
else
{
while(1)
{
if (
prev->dez_op == DEZ_OP_DO || /* do{...}while() */
prev->dez_op == DEZ_OP_WHILE && prev->zop->opcode == ZEND_JMP /* while(true) */
)
{
break;
}
sub = dez_get_last_sub_node(prev);
if (sub == NULL)
{
break;
}
prev = sub;
}
return get_zend_linenum(prev);
}
}
static int dez_in_branch(DEZ_NODE *node, unsigned char parent_dop)
{
DEZ_NODE *p;
int i;
p = node;
while(1)
{
p = get_parent_node(p);
if (p == NULL)
{
return -1;
}
if (
p->dez_op == DEZ_OP_FUNCTION ||
p->dez_op == DEZ_OP_CLASS
)
{
break;
}
if (p->dez_op == parent_dop)
{
return 0;
}
}
return -1;
}
static int dez_get_dest (DEZ_NODE *node)
{
int dest = 0;
if (node == NULL)
{
return 0;
}
if (
node->dez_op == DEZ_OP_FUNCTION ||
node->dez_op == DEZ_OP_CLASS
)
{
return 1000000;
}
if (node->zop != NULL)
{
if
(
node->zop->opcode == ZEND_JMP &&
node->zop->op1.op_type == IS_UNUSED
)
{
dest = node->zop->op1.u.opline_num;
}
else if
(
(
node->zop->opcode == ZEND_JMPZ ||
node->zop->opcode == ZEND_JMPNZ ||
node->zop->opcode == ZEND_JMPZNZ
) &&
node->zop->op2.op_type == IS_UNUSED
)
{
dest = node->zop->op2.u.opline_num;
}
else if
(
node->dez_op == DEZ_OP_CASE &&
(
ZEND_GET_ORI(node->zop)[1].opcode == ZEND_JMPZ ||
ZEND_GET_ORI(node->zop)[1].opcode == ZEND_JMPZNZ
) &&
ZEND_GET_ORI(node->zop)[1].op2.op_type == IS_UNUSED
)
{
dest = ZEND_GET_ORI(node->zop)[1].op2.u.opline_num;
}
else if
(
node->dez_op == DEZ_OP_FOREACH &&
ZEND_GET_ORI(node->zop)[1].opcode == ZEND_FE_FETCH &&
ZEND_GET_ORI(node->zop)[1].op2.op_type == IS_UNUSED
)
{
dest = ZEND_GET_ORI(node->zop)[1].op2.u.opline_num;
}
}
return dest;
}
static int dez_get_branch_end (DEZ_NODE *parent)
{
int i;
int dest, mindest;
DEZ_NODE *header;
DEZ_NODE *pp = NULL;
if (parent == NULL)
{
return 100000;
}
header = parent;
while (header->prev != NULL)
{
header = header->prev;
}
i = m_node_num-1;
while (i >= 0)
{
pp = m_node_stack[i];
if (
pp->dez_op == DEZ_OP_FUNCTION ||
pp->dez_op == DEZ_OP_CLASS
)
{
pp = NULL;
break;
}
if (((DEZ_NODE_EXPR *)(pp->content))->branch_node == header)
{
break;
}
i--;
}
if (i < 0) /* the parent node was not found */
{
pp = NULL;
}
mindest = 100000;
while (i >= 0)
{
DEZ_NODE *ppp = m_node_stack[i];
if (
ppp->dez_op == DEZ_OP_FUNCTION ||
ppp->dez_op == DEZ_OP_CLASS
)
{
break;
}
dest = dez_get_dest(ppp);
if (dest > get_zend_linenum(ppp)) /* goto foreward */
{
if (dest < mindest)
{
mindest = dest;
}
}
i--;
}
dest = dez_get_dest(parent);
if (dest < get_zend_linenum(parent)) /* goto afterward */
{
dest = mindest;
}
else if (dest > mindest)
{
dest = mindest;
}
return dest;
}
static DEZ_NODE *dez_list_get_last_fetch (DEZ_NODE *node)
{
if (node == NULL)
{
return NULL;
}
if (node->dez_op == DEZ_OP_ASSIGN)
{
DEZ_NODE_EXPR *c = (DEZ_NODE_EXPR *)(node->content);
DEZ_NODE *fetch, *prev;
if (c == NULL)
{
return NULL;
}
fetch = c->op2_node;
prev = NULL;
while (fetch != NULL)
{
if (fetch->dez_op != DEZ_OP_FETCH_DIM)
{
break;
}
prev = fetch;
fetch = ((DEZ_NODE_EXPR *)(fetch->content))->op1_node;
}
return prev;
}
return NULL;
}
static int dez_list_get_base_level (DEZ_NODE *list, DEZ_NODE *node)
{
DEZ_NODE_LIST *lc;
DEZ_NODE *fetch;
DEZ_NODE *last_fetch;
int n;
if (list == NULL)
{
return 0;
}
last_fetch = dez_list_get_last_fetch(node);
if (last_fetch == NULL)
{
return 0;
}
lc = (DEZ_NODE_LIST *)(list->content);
fetch = lc->dest_node;
n = 0;
while (fetch != NULL && fetch->dez_op == DEZ_OP_FETCH_DIM)
{
if (
fetch->zop->op1.op_type == last_fetch->zop->op1.op_type &&
fetch->zop->op1.u.var == last_fetch->zop->op1.u.var
)
{
return lc->level - n;
}
fetch = ((DEZ_NODE_EXPR *)(fetch->content))->op1_node;
n++;
}
return 0;
}
static int dez_list_get_level (DEZ_NODE *list, DEZ_NODE *node)
{
int level;
if (node == NULL)
{
return -1;
}
if (node->dez_op == DEZ_OP_ASSIGN)
{
DEZ_NODE_EXPR *c = (DEZ_NODE_EXPR *)(node->content);
DEZ_NODE *fetch;
if (c == NULL)
{
return -1;
}
level = 0;
fetch = c->op2_node;
while (fetch != NULL)
{
if (fetch->dez_op != DEZ_OP_FETCH_DIM)
{
break;
}
level++;
fetch = ((DEZ_NODE_EXPR *)(fetch->content))->op1_node;
}
return level + dez_list_get_base_level(list, node);
}
else if (node->dez_op == DEZ_OP_LIST)
{
DEZ_NODE_LIST *c = (DEZ_NODE_LIST *)(node->content);
return c->level;
}
return -1;
}
static int dez_list_get_lei (DEZ_NODE *list, DEZ_NODE *node, int level)
{
DEZ_NODE *fetch;
int maxl;
int n;
if (
list == NULL ||
node == NULL ||
level <= 0
)
{
return 10000;
}
if (node->dez_op == DEZ_OP_ASSIGN)
{
DEZ_NODE_EXPR *c;
c = (DEZ_NODE_EXPR *)(node->content);
fetch = c->op2_node;
}
else if (node->dez_op == DEZ_OP_LIST)
{
DEZ_NODE_LIST *c;
c = (DEZ_NODE_LIST *)(node->content);
fetch = c->dest_node;
if (fetch != NULL)
{
fetch = ((DEZ_NODE_EXPR *)(fetch->content))->op1_node;
}
}
else if (node->dez_op == DEZ_OP_LE)
{
if (level == ((DEZ_NODE_LIST *)(list->content))->level + 1)
{
return ((DEZ_NODE_LE *)(node->content))->pos;
}
return 10000;
}
maxl = dez_list_get_level (list, node);
if (maxl < level)
{
return 10000;
}
n = maxl - level;
while (n > 0)
{
if (
fetch == NULL ||
fetch->dez_op != DEZ_OP_FETCH_DIM
)
{
return 10000;
}
fetch = ((DEZ_NODE_EXPR *)(fetch->content))->op1_node;
n--;
}
if (
fetch == NULL ||
fetch->dez_op != DEZ_OP_FETCH_DIM
)
{
return 10000;
}
return fetch->zop->op2.u.var;
}
static DEZ_NODE *dez_list_fetch_sub_dest (DEZ_NODE *node)
{
if (node == NULL)
{
return NULL;
}
if (node->dez_op == DEZ_OP_ASSIGN)
{
DEZ_NODE_EXPR *c = (DEZ_NODE_EXPR *)(node->content);
DEZ_NODE *fetch;
if (c == NULL)
{
return NULL;
}
fetch = c->op2_node;
c->op2_node = NULL;
return fetch;
}
else if (node->dez_op == DEZ_OP_LIST)
{
DEZ_NODE_LIST *c = (DEZ_NODE_LIST *)(node->content);
DEZ_NODE *fetch;
if (c->dest_node == NULL)
{
return NULL;
}
fetch = ((DEZ_NODE_EXPR *)(c->dest_node->content))->op1_node;
((DEZ_NODE_EXPR *)(c->dest_node->content))->op1_node = NULL;
return fetch;
}
return NULL;
}
static DEZ_NODE *dez_list_create (int level)
{
DEZ_NODE *node;
DEZ_NODE_LIST *content;
content = (DEZ_NODE_LIST *)malloc(sizeof(DEZ_NODE_LIST));
if (content == NULL)
{
return NULL;
}
node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
if (node == NULL)
{
free(content);
return NULL;
}
content->branch_node = NULL;
content->le_node = NULL;
content->dest_node = NULL;
content->level = level;
node->dez_op = DEZ_OP_LIST;
node->zop = NULL;
node->content = content;
node->prev = NULL;
node->next = NULL;
return node;
}
static int dez_list_add_le (DEZ_NODE *list, DEZ_NODE *node, int node_level)
{
DEZ_NODE *le, *sl;
DEZ_NODE_LIST *lc;
DEZ_NODE_LE *lec;
int level;
lc = (DEZ_NODE_LIST *)(list->content);
if (node_level > 0)
{
level = node_level;
}
else
{
level = dez_list_get_level(list, node);
if (level <= 0)
{
return -1;
}
}
if (level > lc->level+1)
{
/*-- search sub list --*/
int lei = dez_list_get_lei(list, node, lc->level+1);
le = lc->le_node;
while (le != NULL)
{
if (
((DEZ_NODE_LE *)(le->content))->a_node->dez_op == DEZ_OP_LIST &&
lei == dez_list_get_lei (list, le, lc->level+1)
)
{
break;
}
le = le->next;
}
if (le != NULL) /* the sub list is found --*/
{
dez_list_add_le(((DEZ_NODE_LE *)(le->content))->a_node, node, level);
}
else
{
sl = dez_list_create(lc->level+1);
dez_list_add_le(sl, node, level);
dez_list_add_le(list, sl, lc->level+1);
}
}
else if (level == lc->level+1)
{
int lei;
lec = (DEZ_NODE_LE *)malloc(sizeof(DEZ_NODE_LE));
if (lec == NULL)
{
return -1;
}
le = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
if (le == NULL)
{
free(lec);
return -1;
}
lei = dez_list_get_lei(list, node, level);
lec->branch_node = NULL;
lec->a_node = node;
lec->pos = lei;
le->dez_op = DEZ_OP_LE;
le->zop = node->zop;
le->content = lec;
le->prev = NULL;
le->next = NULL;
if (lc->le_node == NULL) /* the list is empty */
{
lc->le_node = le;
lc->dest_node = dez_list_fetch_sub_dest(node);
list->zop = node->zop;
}
else
{
DEZ_NODE *prev, *le1;
le1 = lc->le_node;
prev= NULL;
while(le1 != NULL)
{
int le1_lei = dez_list_get_lei(list, le1, level);
if (le1_lei == lei) /* the element is exist */
{
free(lec);
free(le);
return -1;
}
else if (le1_lei > lei)
{
break;
}
prev = le1;
le1 = le1->next;
}
if (prev == NULL) /* the first element added */
{
le->next = lc->le_node;
lc->le_node = le;
if (le->next != NULL) le->next->prev = le;
}
else
{
le->next = prev->next;
le->prev = prev;
if (le->next != NULL) le->next->prev = le;
if (le->prev != NULL) le->prev->next = le;
}
}
}
else
{
sl = dez_list_create(lc->level-1);
sl->next = list->next;
sl->prev = list->prev;
if (sl->next != NULL) sl->next->prev = sl;
if (sl->prev != NULL) sl->prev->next = sl;
list->next = NULL;
list->prev = NULL;
if (list == m_dez_op_current)
{
m_dez_op_current = sl;
}
dez_list_add_le(sl, list, lc->level);
dez_list_add_le(sl, node, level);
}
return 0;
}
static int dez_list_is_le (DEZ_NODE *node)
{
DEZ_NODE *last_fetch;
DEZ_NODE_EXPR *expr;
last_fetch = dez_list_get_last_fetch(node);
if (last_fetch == NULL)
{
return -1;
}
expr = (DEZ_NODE_EXPR *)(last_fetch->content);
if (
expr != NULL &&
expr->op1_node == NULL &&
(last_fetch->zop->op1.op_type == IS_TMP_VAR || last_fetch->zop->op1.op_type == IS_VAR)
)
{
return 0;
}
return -1;
}
static DEZ_NODE *dez_list_find_dest (DEZ_NODE *le)
{
DEZ_NODE *p = m_dez_op_current;
DEZ_NODE *last_fetch = dez_list_get_last_fetch(le);
if (last_fetch == NULL)
{
return NULL;
}
while(p != NULL)
{
DEZ_NODE_EXPR *c;
DEZ_NODE *fetch;
if (p->dez_op != DEZ_OP_ASSIGN)
{
p = p->prev;
continue;
}
c = (DEZ_NODE_EXPR *)(p->content);
if (c == NULL)
{
p = p->prev;
continue;
}
fetch = c->op2_node;
while (fetch != NULL)
{
if (
fetch->dez_op == DEZ_OP_FETCH_DIM &&
((DEZ_NODE_EXPR *)(fetch->content))->op1_node != NULL &&
fetch->zop->op1.op_type == last_fetch->zop->op1.op_type &&
fetch->zop->op1.u.var == last_fetch->zop->op1.u.var
)
{
return p;
}
fetch = ((DEZ_NODE_EXPR *)(fetch->content))->op1_node;
}
p = p->prev;
}
return NULL;
}
static int dez_list_is_dest (DEZ_NODE *node, znode *zn)
{
if (node->dez_op == DEZ_OP_LIST)
{
DEZ_NODE_LIST *c = (DEZ_NODE_LIST *)(node->content);
if (
c != NULL &&
c->dest_node != NULL &&
c->dest_node->zop != NULL &&
c->dest_node->zop->op1.op_type == zn->op_type &&
c->dest_node->zop->op1.u.var == zn->u.var
)
{
return 0;
}
}
return -1;
}
static DEZ_NODE *find_tmp_node (znode *zn)
{
DEZ_NODE *p = m_dez_op_current;
while(p != NULL)
{
if (
p->zop != NULL &&
p->zop->result.op_type == zn->op_type &&
p->zop->result.u.var == zn->u.var
)
{
return p;
}
p = p->prev;
}
return NULL;
}
static DEZ_NODE *fetch_node (DEZ_NODE *node)
{
if (node == NULL || node->prev == NULL)
{
return NULL;
}
node->prev->next = node->next;
if (node->next != NULL) node->next->prev = node->prev;
if (node == m_dez_op_current)
{
m_dez_op_current = node->prev;
}
node->prev = NULL;
node->next = NULL;
return node;
}
static DEZ_NODE *fetch_current_node (void)
{
DEZ_NODE *p = m_dez_op_current;
if (p == NULL || p->prev == NULL)
{
return NULL;
}
p->prev->next = NULL;
m_dez_op_current = p->prev;
p->prev = NULL;
return p;
}
static DEZ_NODE *fetch_tmp_node (znode *zn)
{
DEZ_NODE *p = m_dez_op_current;
zend_op *zop = m_zend_op_current-m_opc_num;
if (zn->op_type == IS_TMP_VAR || zn->op_type == IS_VAR)
{
while (zop >= m_zend_op_start)
{
if (
zop->result.op_type == zn->op_type &&
zop->result.u.var == zn->u.var
)
{
break;
}
zop--;
}
if (zop < m_zend_op_start) /* not found */
{
return NULL;
}
while(p != NULL)
{
if (p->zop != NULL)
{
if (p->zop < zop)
{
break;
}
else if (
p->zop->result.op_type == zn->op_type &&
p->zop->result.u.var == zn->u.var
)
{
if (p->prev != NULL) p->prev->next = p->next;
if (p->next != NULL) p->next->prev = p->prev;
if (p == m_dez_op_current)
{
m_dez_op_current = p->prev;
}
p->prev = NULL;
p->next = NULL;
return p;
}
}
p = p->prev;
}
}
/*-- fetch list node --*/
p = m_dez_op_current;
if(p != NULL)
{
if (dez_list_is_dest(p, zn) == 0)
{
if (p->prev != NULL) p->prev->next = p->next;
if (p->next != NULL) p->next->prev = p->prev;
m_dez_op_current = p->prev;
p->prev = NULL;
p->next = NULL;
return p;
}
}
return NULL;
}
static DEZ_NODE *fetch_call_ini_node (znode *zn)
{
DEZ_NODE *p = fetch_tmp_node(zn);
if (p != NULL)
{
return p;
}
if (
zn->op_type == IS_CONST &&
zn->u.constant.type == IS_STRING
)
{
p = m_dez_op_current;
while(p != NULL)
{
if (
p->dez_op == DEZ_OP_CALL_INIT &&
p->zop != NULL &&
p->zop->op2.op_type == IS_CONST &&
p->zop->op2.u.constant.type == IS_STRING&&
strcmp((char *)(p->zop->op2.u.var), (char *)(zn->u.var)) == 0
)
{
return fetch_node(p);
}
p = p->prev;
}
}
else
{
p = m_dez_op_current;
while(p != NULL)
{
if (
p->dez_op == DEZ_OP_CALL_INIT &&
p->zop != NULL &&
p->zop->op2.op_type == zn->op_type &&
// p->zop->op2.u.constant.type == zn->u.constant.type &&
p->zop->op2.u.var == zn->u.var
)
{
return fetch_node(p);
}
p = p->prev;
}
}
return NULL;
}
static DEZ_NODE *fetch_jmp_src_node (int jmpcode, int dest)
{
DEZ_NODE *p = m_dez_op_current;
while(p != NULL)
{
if (
p->zop != NULL &&
p->zop->opcode == jmpcode &&
p->zop->op2.op_type == IS_UNUSED &&
p->zop->op2.u.opline_num == dest
)
{
if (p->prev != NULL) p->prev->next = p->next;
if (p->next != NULL) p->next->prev = p->prev;
if (p == m_dez_op_current)
{
m_dez_op_current = p->prev;
}
p->prev = NULL;
p->next = NULL;
return p;
}
p = p->prev;
}
return NULL;
}
static DEZ_NODE *get_jmp_dest_node (int dest)
{
DEZ_NODE *p = m_dez_op_current;
if (
p->zop != NULL &&
get_zend_linenum(p) < dest
)
{
return NULL;
}
while(p->prev != NULL)
{
if (
p->prev->zop != NULL &&
get_zend_linenum(p->prev) < dest
)
{
break;
}
p = p->prev;
}
if (p->prev == NULL)
{
p = p->next;
}
return p;
}
static DEZ_NODE *fetch_jmp_dest_node (int dest)
{
DEZ_NODE *p = get_jmp_dest_node(dest);
if (p == NULL)
{
return NULL;
}
m_dez_op_current = p->prev;
m_dez_op_current->next = NULL;
p->prev = NULL;
return p;
}
static DEZ_NODE *find_last_node (int dez_op)
{
DEZ_NODE *p = m_dez_op_current;
while(p != NULL)
{
if (p->dez_op == dez_op)
{
break;
}
p = p->prev;
}
return p;
}
static DEZ_NODE *find_last_node_ex (int dez_op, znode *result, znode *op1, znode *op2)
{
DEZ_NODE *p = m_dez_op_current;
znode *zn;
while(p != NULL)
{
if (p->dez_op == dez_op)
{
int found = 1;
if (result != NULL)
{
zn = &(p->zop->result);
if (
zn->op_type != result->op_type ||
zn->u.var != result->u.var
)
{
found = 0;
}
}
if (op1 != NULL)
{
zn = &(p->zop->op1);
if (
zn->op_type != op1->op_type ||
zn->u.var != op1->u.var
)
{
found = 0;
}
}
if (op2 != NULL)
{
zn = &(p->zop->op2);
if (
zn->op_type != op2->op_type ||
zn->u.var != op2->u.var
)
{
found = 0;
}
}
if (found != 0)
{
return p;
}
}
p = p->prev;
}
return NULL;
}
static int dez_is_first_node (DEZ_NODE *node)
{
if (node == NULL)
{
return 0;
}
node = node->prev;
while (node != NULL)
{
if (node->dez_op != DEZ_OP_NOP)
{
return -1;
}
node = node->prev;
}
return 0;
}
static int dez_branch_get_range (DEZ_NODE *parent, int *header, int *tailer)
{
if (
parent == NULL ||
parent->content == NULL ||
header == NULL ||
tailer == NULL
)
{
return -1;
}
if (parent->dez_op == DEZ_OP_FOR)
{
DEZ_NODE *before_node = ((DEZ_NODE_FOR *)(parent->content))->before_node;
if (before_node != NULL)
{
*header = get_zend_linenum(before_node)+1;
}
else
{
*header = get_prev_zend_linenum(parent)+1;
}
}
else
{
*header = get_prev_zend_linenum(parent)+1;
}
if (
parent->dez_op == DEZ_OP_DO || /* do{...}while() */
parent->dez_op == DEZ_OP_WHILE && parent->zop->opcode == ZEND_JMP /* while(true) */
)
{
*tailer = get_zend_linenum(parent);
}
else
{
DEZ_NODE *lastnode;
lastnode = parent;
while(1)
{
DEZ_NODE *sub;
sub = dez_get_last_sub_node(lastnode);
if (sub == NULL) /* no sub node */
{
break;
}
lastnode = sub;
if (
lastnode->dez_op == DEZ_OP_DO || /* do{...}while() */
lastnode->dez_op == DEZ_OP_WHILE && lastnode->zop->opcode == ZEND_JMP /* while(true) */
)
{
break;
}
}
*tailer = get_zend_linenum(lastnode);
}
return 0;
}
static int dez_enter_branch (void)
{
DEZ_NODE_EXPR *content;
content = (DEZ_NODE_EXPR *)(m_dez_op_current->content);
if (content->branch_node == NULL)
{
content->branch_node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
if (content->branch_node == NULL)
{
return -1;
}
content->branch_node->dez_op = DEZ_OP_NOP;
content->branch_node->zop = NULL;
content->branch_node->content = NULL;
content->branch_node->prev = NULL;
content->branch_node->next = NULL;
}
dez_node_push(m_dez_op_current);
m_dez_op_current = content->branch_node;
return 0;
}
static int dez_enter_branch_ex (DEZ_NODE *node)
{
DEZ_NODE_EXPR *content;
content = (DEZ_NODE_EXPR *)(node->content);
content->branch_node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
if (content->branch_node == NULL)
{
return -1;
}
dez_node_push(node);
content->branch_node->dez_op = DEZ_OP_NOP;
content->branch_node->zop = NULL;
content->branch_node->content = NULL;
content->branch_node->prev = NULL;
content->branch_node->next = node->next;
if (content->branch_node->next != NULL) content->branch_node->next->prev = content->branch_node;
if (node == m_dez_op_current)
{
m_dez_op_current = content->branch_node;
}
return 0;
}
// enterelse = 0: don't enter else node, 1: enter else node
static int dez_exit_branch (int enterelse)
{
DEZ_NODE *node, *els, *tmp, *m_dez_op_current2;
DEZ_NODE_EXPR *content;
int nextline, dest;
int remove_node = 0;
int dup_jmp = 0;
zend_op *cur_zop;
node = dez_node_pop();
if (node == NULL)
{
return -1;
}
cur_zop = ZEND_GET_ORI(m_zend_op_current) - m_opc_num + m_zend_op_match_n;
content = (DEZ_NODE_EXPR *)(node->content);
m_dez_op_current2 = NULL;
els = NULL;
nextline = ZEND_LINENUM(cur_zop) + 1;
if (node->dez_op == DEZ_OP_IF) /* if */
{
if (
enterelse == 1 && /* need enter else node */
node->zop->opcode != ZEND_JMP /* not if (false) */
)
{
int dest;
dest = dez_get_dest(node);
if (dest == nextline) /* there maybe is else node */
{
DEZ_NODE *lastnode = NULL;
int jmpdest;
tmp = dez_get_last_sub_node(node);
while(tmp != NULL)
{
lastnode = tmp;
tmp = dez_get_last_sub_node(tmp);
}
jmpdest = dez_get_dest(lastnode);
if (
lastnode != NULL &&
lastnode->dez_op == DEZ_OP_IF && /* if */
lastnode->zop->opcode == ZEND_JMP && /* if (false) */
(jmpdest > dest || jmpdest <= get_prev_zend_linenum(node)) && /* has some zend ops */
// dez_get_branch_end(lastnode) > dest && /* has some zend ops */
dez_branch_is_null(lastnode) == 0 /* the sub branch is null */
)
{
m_dez_op_current = node;
dez_node_cvt_if(DEZ_OP_ELSE, lastnode->zop);/* add else node */
dez_enter_branch(); /* enter else node */
return 0;
}
}
}
}
else if (
node->dez_op == DEZ_OP_CASE || /* case of switch */
node->dez_op == DEZ_OP_DEFAULT /* default of switch */
)
{
m_dez_op_current2 = content->op1_node; /* return to switch node */
}
else if (node->dez_op == DEZ_OP_ELSE) /* else node */
{
if (dez_branch_is_null(node) == 0) /* the branch is null */
{
tmp = node->prev;
tmp->next = node->next;
node->prev = NULL;
m_dez_op_current2 = tmp;
remove_node = 1;
}
}
if (m_dez_op_current2 == NULL)
{
m_dez_op_current = node;
}
else
{
m_dez_op_current = m_dez_op_current2;
}
if (node != NULL)
{
DEZ_NODE *lastsubnode = dez_get_last_sub_node(node);
dest = dez_get_dest(node);
#if 0
if (
dest >= nextline &&
node->dez_op == DEZ_OP_IF && node->zop->opcode == ZEND_JMP && /* maybe break */
lastsubnode != NULL &&
lastsubnode->dez_op == DEZ_OP_IF && lastsubnode->zop->opcode == ZEND_JMP /* if (false) */
)
{
DEZ_NODE *pp = dez_node_get();
if (
pp != NULL &&
pp->dez_op == DEZ_OP_IF && pp->zop->opcode != ZEND_JMP
)
{
int ppbegin = get_prev_zend_linenum(pp);
int ppend = dez_get_branch_end(pp);
if (
(int)(node->zop->op1.u.opline_num) <= ppbegin &&
(int)(node->zop->op1.u.opline_num) > ppend && /* jmp out of branch of node */
(int)(lastsubnode->zop->op1.u.opline_num) <= ZEND_LINENUM(pp->zop) &&
(int)(lastsubnode->zop->op1.u.opline_num) > ppbegin /* jmp to header of pp */
)
{
dez_node_cvt_jmp(DEZ_OP_JMP, lastsubnode->zop);
return 0;
}
}
}
#endif
if (dest <= get_zend_linenum(node)) /* jump afterward */
{
dup_jmp = 1;
}
else if (dest >= nextline)
{
// if (cur_zop->opcode == ZEND_JMP)
if (
lastsubnode != NULL &&
lastsubnode->dez_op == DEZ_OP_IF && lastsubnode->zop->opcode == ZEND_JMP /* if (false) */
)
{
int dest_is_case_default = 0;
zend_op *zop_dest = m_zend_op_start + lastsubnode->zop->op1.u.opline_num;
if (
(zop_dest[-1].opcode == ZEND_JMPZ || zop_dest[-1].opcode == ZEND_JMPZNZ) &&
zop_dest[-2].opcode == ZEND_CASE
) /* the dest is 'case' */
{
dest_is_case_default = 1;
}
else if (
zop_dest[-1].opcode == ZEND_BOOL &&
zop_dest[-2].opcode == ZEND_JMP
) /* the dest is 'default' */
{
dest_is_case_default = 1;
}
if (
!(
node->dez_op == DEZ_OP_ELSE &&
dez_in_branch(node, DEZ_OP_CASE) == 0 && /* within case branch */
dest_is_case_default /* the dest node is case or default node */
)
)
{
dup_jmp = 1;
}
}
}
if (dup_jmp != 0)
{
zend_op *dupzop;
dupzop = dez_dup_zend_op(cur_zop);
dupzop->opcode = ZEND_JMP;
dupzop->op1.op_type = IS_UNUSED;
dupzop->op1.u.opline_num = dest;
dupzop->op2.op_type = IS_UNUSED;
dupzop->op2.u.opline_num = 0;
dupzop->result.op_type = IS_UNUSED;
dupzop->result.u.opline_num = 0;
dez_node_cvt_jmp(DEZ_OP_JMP, dupzop);
}
}
if (remove_node != 0)
{
dez_node_specs[node->dez_op].dez_node_free_func(node); /* remove the else node */
}
return 0;
}
static int dez_check_exit_branch (void)
{
DEZ_NODE *node;
int nextline,dest;
int i;
nextline = ZEND_LINENUM(m_zend_op_current) - m_opc_num + m_zend_op_match_n + 1;
for (i = 0; i < m_node_num; i++)
{
node = m_node_stack[i];
if (
node->dez_op == DEZ_OP_FUNCTION ||
node->dez_op == DEZ_OP_CLASS
)
{
continue;
}
dest = dez_get_branch_end(node);
if (dest <= nextline)
{
break;
}
}
#if 0
if (i < m_node_num) /* found */
{
int n = m_node_num - 1;
/*-- exit child branch tree --*/
while (n > i)
{
dez_exit_branch(0);
n--;
}
dez_exit_branch(1); /* exit self */
}
#endif
while (i+1 < m_node_num)
{
dez_exit_branch(0);
}
if (i < m_node_num)
{
dez_exit_branch(1);
}
return 0;
}
static int dez_check_exit_all (void)
{
while(m_node_num > 0)
{
DEZ_NODE *node = dez_node_get();
if (
node->dez_op == DEZ_OP_FUNCTION ||
node->dez_op == DEZ_OP_CLASS
)
{
break;
}
dez_exit_branch(0);
}
return 0;
}
#if 0
static int dez_check_exit_branch (void)
{
int nextline;
DEZ_NODE *tmp, *node, *els;
DEZ_NODE_EXPR *content;
int i,j;
nextline = ZEND_LINENUM(m_zend_op_current - m_opc_num) + 1;
for (i = 0; i < m_node_num; i++)
{
int dest;
node = m_node_stack[i];
if (
node->dez_op == DEZ_OP_FUNCTION ||
node->dez_op == DEZ_OP_CLASS
)
{
continue;
}
content = (DEZ_NODE_EXPR *)(node->content);
dest = dez_get_dest(node);
if (
dest > get_zend_linenum(node) && /* jump forward */
dest <= nextline
)
{
m_dez_op_current = node;
els = NULL;
if (
node->dez_op == DEZ_OP_IF && /* if */
node->zop->opcode != ZEND_JMP /* not if (false) */
)
{
tmp = dez_node_get();
if (
node != tmp &&
tmp != NULL &&
tmp->dez_op == DEZ_OP_IF && /* if */
tmp->zop->opcode == ZEND_JMP && /* if (false) */
dez_get_dest(tmp) > nextline && /* has some zend ops */
dez_branch_is_null(tmp) == 0 /* the sub branch is null */
)
{
els = dez_node_pop();
els->dez_op = DEZ_OP_ELSE;
els = fetch_node(els);
}
}
else if (
node->dez_op == DEZ_OP_CASE || /* case of switch */
node->dez_op == DEZ_OP_DEFAULT /* default of switch */
)
{
m_dez_op_current = content->op1_node; /* return to switch node */
}
/*-- exit all child branchs --*/
while (m_node_num > i)
{
node = m_node_stack[m_node_num-1];
if (node->dez_op == DEZ_OP_ELSE) /* else node */
{
if (dez_branch_is_null(node) == 0) /* the branch is null */
{
tmp = node->prev;
if (m_dez_op_current == node)
{
m_dez_op_current = tmp;
}
tmp->next = node->next;
node->prev = NULL;
dez_node_specs[node->dez_op].dez_node_free_func(node); /* remove the else node */
node = tmp;
}
}
else if (node->dez_op == DEZ_OP_IF && node->zop->opcode == ZEND_JMP) /* if (false) */
{
DEZ_NODE_IF *ifc = (DEZ_NODE_IF *)(node->content);
#if 0
node->next = ifc->branch_node->next; /* moveup all sub node */
ifc->branch_node->next = NULL;
dez_node_specs[ifc->branch_node->dez_op].dez_node_free_func(ifc->branch_node);
ifc->branch_node = NULL;
#endif
node->dez_op = DEZ_OP_JMP; /* change this node into JMP (maybe break) */
}
m_node_num--;
}
if (els != NULL)
{
DEZ_ADD_NODE(els);
dez_enter_branch(); /* enter else branch */
}
break;
}
}
return 0;
}
#endif
/*-- convertor for DEZ_NODE_NOP --*/
static int dez_node_cvt_nop (unsigned char dez_op, zend_op *pzop)
{
return 0;
}
/*-- convertor for expr --*/
static int dez_node_cvt_expr (unsigned char dez_op, zend_op *pzop)
{
DEZ_NODE *parent, *node;
DEZ_NODE_EXPR *content, *c;
parent = dez_node_get();
content = (DEZ_NODE_EXPR *)malloc(sizeof(DEZ_NODE_EXPR));
if (content == NULL)
{
return -1;
}
node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
if (node == NULL)
{
free(content);
return -1;
}
content->branch_node = NULL;
content->op1_node = fetch_tmp_node(&(pzop->op1));
content->op2_node = fetch_tmp_node(&(pzop->op2));
node->dez_op = dez_op;
node->zop = pzop;
node->content = content;
node->prev = NULL;
node->next = NULL;
if (
dez_op == DEZ_OP_ASSIGN &&
parent != NULL &&
parent->dez_op == DEZ_OP_FOREACH
)
{
DEZ_NODE_FOREACH *fe = (DEZ_NODE_FOREACH *)(parent->content);
if (
content->op2_node != NULL &&
content->op2_node->zop->opcode == ZEND_FETCH_DIM_TMP_VAR &&
content->op2_node->zop->op1.op_type == ZEND_GET_ORI(parent->zop)[1].result.op_type &&
content->op2_node->zop->op1.u.var == ZEND_GET_ORI(parent->zop)[1].result.u.var
)
{
if (
fe->value_node == NULL &&
content->op2_node->zop->op2.u.var == 0
)
{
node->dez_op = DEZ_OP_AS;
fe->value_node = node;
return 0;
}
else if
(
fe->key_node == NULL &&
content->op2_node->zop->op2.u.var == 1
)
{
node->dez_op = DEZ_OP_AS;
fe->key_node = node;
return 0;
}
}
else if (content->op2_node == NULL)
{
if (
fe->value_node == NULL &&
pzop->op2.op_type == ZEND_GET_ORI(parent->zop)[1].result.op_type &&
pzop->op2.u.var == ZEND_GET_ORI(parent->zop)[1].result.u.var
)
{
node->dez_op = DEZ_OP_AS;
fe->value_node = node;
return 0;
}
}
}
if (
dez_op == DEZ_OP_ASSIGN &&
content->op2_node != NULL &&
content->op2_node->dez_op == DEZ_OP_FETCH_DIM
)
{
DEZ_NODE *fetch = dez_list_get_last_fetch(node);
if (fetch != NULL)
{
c = (DEZ_NODE_EXPR *)(fetch->content);
if (
c->op1_node != NULL &&
c->op1_node->dez_op == DEZ_OP_LIST /* list element */
)
{
DEZ_NODE *list = c->op1_node;
c->op1_node = NULL;
DEZ_ADD_NODE(list);
dez_list_add_le(list, node, -1); /* add element into list */
return 0;
}
}
}
if (dez_list_is_le(node) == 0) /* list element */
{
int level;
DEZ_NODE *list, *dest;
dest = dez_list_find_dest(node);
if (dest != NULL)
{
fetch_node(dest);
level = dez_list_get_level(NULL, dest);
list = dez_list_create(level-1); /* create an empty list */
dez_list_add_le(list, dest, level);
DEZ_ADD_NODE(list);
}
else
{
list = find_last_node(DEZ_OP_LIST);
}
if (list != NULL)
{
dez_list_add_le(list, node, -1);
return 0;
}
}
DEZ_ADD_NODE(node);
if (dez_op == DEZ_OP_QM_ASSIGN && (m_opc_num < 2 || ZEND_GET_ORI(pzop)[1].opcode != ZEND_JMP)) /* qm false */
{
return 2; /* exit branch */
}
else
{
return 0;
}
}
/*-- convertor for if --*/
static int dez_node_cvt_if (unsigned char dez_op, zend_op *pzop)
{
DEZ_NODE *parent, *node;
DEZ_NODE_IF *content;
parent = dez_node_get();
if (dez_op == DEZ_OP_IF && pzop->opcode != ZEND_JMP)
{
DEZ_NODE *current_node = m_dez_op_current;
while(current_node != NULL)
{
if (
current_node->dez_op == DEZ_OP_IF &&
current_node->zop->opcode == ZEND_JMP
) /* if (false) */
{
current_node = current_node->prev;
continue;
}
else if
(
current_node->dez_op == DEZ_OP_FUNCTION ||
current_node->dez_op == DEZ_OP_CLASS
)
{
current_node = NULL;
}
break;
}
node = find_tmp_node(&(pzop->op1));
if (
node != NULL &&
node->dez_op == DEZ_OP_SWITCH &&
current_node == node &&
ZEND_LINENUM(pzop) >= pzop->op2.u.opline_num /* ZEND_JMPZ: goto afterward */
) /* the end of default of switch */
{
return 0;
}
}
content = (DEZ_NODE_IF *)malloc(sizeof(DEZ_NODE_IF));
if (content == NULL)
{
return -1;
}
node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
if (node == NULL)
{
free(content);
return -1;
}
content->branch_node = NULL;
if (pzop->opcode == ZEND_JMP) /* if (false) or else */
{
content->op1_node = NULL;
content->op2_node = NULL;
content->dest = pzop->op1.u.opline_num;
}
else
{
content->op1_node = fetch_tmp_node(&(pzop->op1));
content->op2_node = fetch_tmp_node(&(pzop->op2));
content->dest = pzop->op2.u.opline_num;
}
node->dez_op = dez_op;
node->zop = pzop;
node->content = content;
node->prev = NULL;
node->next = NULL;
DEZ_ADD_NODE(node);
if (dez_op == DEZ_OP_IF)
{
return 1; /* enter branch */
}
else
{
return 0;
}
}
/*-- convertor for DEZ_OP_QM_ASSIGN --*/
static int dez_node_cvt_qm_assign (unsigned char dez_op, zend_op *pzop)
{
DEZ_NODE *node;
DEZ_NODE_EXPR *content;
content = (DEZ_NODE_EXPR *)malloc(sizeof(DEZ_NODE_EXPR));
if (content == NULL)
{
return -1;
}
node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
if (node == NULL)
{
free(content);
return -1;
}
content->branch_node = NULL;
content->op1_node = fetch_tmp_node(&(pzop->op1));
if (m_opc_num >= 2 && ZEND_GET_ORI(pzop)[1].opcode == ZEND_JMP) /* qm true */
{
DEZ_NODE *cond;
/*-- fetch qm condition node --*/
// content->op2_node = fetch_jmp_src_node (ZEND_JMPZ, (ZEND_LINENUM(pzop)+2);
cond = dez_node_get();
if (
cond != NULL &&
cond->dez_op == DEZ_OP_IF &&
((DEZ_NODE_IF *)(cond->content))->dest == ZEND_LINENUM(pzop)+2
)
{
content->op2_node = dez_node_pop(); /* fetch the condition node */
m_dez_op_current = content->op2_node->prev;
content->op2_node->prev = NULL;
}
else
{
content->op2_node = NULL;
}
}
else /* qm false */
{
/*-- fetch qm true node --*/
content->op2_node = fetch_tmp_node (&(pzop->result));
}
node->dez_op = dez_op;
node->zop = pzop;
node->content = content;
DEZ_ADD_NODE(node);
return 0;
}
/*-- convertor for DEZ_OP_DO --*/
static int dez_node_cvt_do (unsigned char dez_op, zend_op *pzop)
{
DEZ_NODE *node;
DEZ_NODE_EXPR *content;
content = (DEZ_NODE_EXPR *)malloc(sizeof(DEZ_NODE_EXPR));
if (content == NULL)
{
return -1;
}
node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
if (node == NULL)
{
free(content);
return -1;
}
content->op1_node = fetch_tmp_node(&(pzop->op1));
content->op2_node = NULL;
content->branch_node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
if (content->branch_node == NULL)
{
return -1;
}
content->branch_node->dez_op = DEZ_OP_NOP;
content->branch_node->zop = NULL;
content->branch_node->content = NULL;
content->branch_node->prev = NULL;
content->branch_node->next = fetch_jmp_dest_node(pzop->op2.u.opline_num);
if (content->branch_node->next != NULL) content->branch_node->next->prev = content->branch_node;
DEZ_ADD_NODE(node);
node->dez_op = dez_op;
node->zop = pzop;
node->content = content;
return 0;
}
/*-- convertor for DEZ_OP_FOR --*/
static int dez_node_cvt_for (unsigned char dez_op, zend_op *pzop)
{
DEZ_NODE *node;
DEZ_NODE_FOR *content;
content = (DEZ_NODE_FOR *)malloc(sizeof(DEZ_NODE_FOR));
if (content == NULL)
{
return -1;
}
node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
if (node == NULL)
{
free(content);
return -1;
}
content->branch_node = NULL;
content->cond_node = fetch_tmp_node(&(pzop->op1));
if (m_dez_op_current->dez_op == DEZ_OP_ASSIGN)
{
content->before_node = fetch_current_node();
}
else
{
content->before_node = NULL;
}
content->after_node = NULL;
node->dez_op = dez_op;
node->zop = pzop;
node->content = content;
DEZ_ADD_NODE(node);
return 1; /* enter branch */
}
/*-- convertor for DEZ_OP_FOREACH --*/
static int dez_node_cvt_foreach (unsigned char dez_op, zend_op *pzop)
{
DEZ_NODE *node;
DEZ_NODE_FOREACH *content;
content = (DEZ_NODE_FOREACH *)malloc(sizeof(DEZ_NODE_FOREACH));
if (content == NULL)
{
return -1;
}
node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
if (node == NULL)
{
free(content);
return -1;
}
content->branch_node = NULL;
content->source_node = fetch_tmp_node(&(pzop->op1));
content->key_node = NULL;
content->value_node = NULL;
node->dez_op = dez_op;
node->zop = pzop;
node->content = content;
DEZ_ADD_NODE(node);
return 1; /* enter branch */
}
/*-- convertor for DEZ_OP_CASE --*/
static int dez_node_cvt_case (unsigned char dez_op, zend_op *pzop)
{
DEZ_NODE *node, *parent, *branch;
DEZ_NODE_EXPR *content, *swcontent;
content = (DEZ_NODE_EXPR *)malloc(sizeof(DEZ_NODE_EXPR));
if (content == NULL)
{
return -1;
}
node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
if (node == NULL)
{
free(content);
return -1;
}
content->branch_node = NULL;
content->op1_node = fetch_tmp_node(&(pzop->op1));
content->op2_node = fetch_tmp_node(&(pzop->op2));
node->dez_op = dez_op;
node->zop = pzop;
node->content = content;
node->prev = NULL;
node->next = NULL;
parent = find_tmp_node(&(pzop->result));
if (parent == NULL)
{
return -1;
}
if (parent->dez_op == DEZ_OP_BOOL)
{
if (
parent->zop->op1.op_type == IS_CONST &&
parent->zop->op1.u.constant.type == IS_BOOL &&
parent->zop->op1.u.constant.value.lval == 0
)
{
parent->dez_op = DEZ_OP_SWITCH;
/* set the condition of switch */
swcontent = (DEZ_NODE_EXPR *)(parent->content);
swcontent->op1_node = content->op1_node;
parent->zop->op1 = pzop->op1;
content->op1_node = NULL;
branch = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
if (branch == NULL)
{
return -1;
}
branch->dez_op = DEZ_OP_NOP;
branch->zop = NULL;
branch->content = NULL;
branch->prev = NULL;
branch->next = NULL;
swcontent->branch_node = branch;
}
else
{
return -1;
}
}
else if (parent->dez_op == DEZ_OP_SWITCH)
{
branch = ((DEZ_NODE_EXPR *)(parent->content))->branch_node;
while(branch->next != NULL) branch = branch->next;
}
else
{
return -1;
}
content->op1_node = parent; /* pointer to switch node */
branch->next = node;
node->prev = branch;
m_dez_op_current= node;
return 1; /* enter case branch */
}
/*-- convertor for DEZ_OP_DEFAULT --*/
static int dez_node_cvt_default (unsigned char dez_op, zend_op *pzop)
{
DEZ_NODE *node, *parent, *branch;
DEZ_NODE_EXPR *content, *swcontent;
content = (DEZ_NODE_EXPR *)malloc(sizeof(DEZ_NODE_EXPR));
if (content == NULL)
{
return -1;
}
node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
if (node == NULL)
{
free(content);
return -1;
}
content->branch_node = NULL;
content->op1_node = NULL;
content->op2_node = NULL;
node->dez_op = dez_op;
node->zop = pzop;
node->content = content;
node->prev = NULL;
node->next = NULL;
while (1)
{
DEZ_NODE *tmp;
parent = find_tmp_node(&(ZEND_GET_ORI(pzop)[1].result));
if (parent != NULL)
{
break;
}
tmp = dez_node_get();
if (tmp == NULL)
{
free(content);
free(node);
return 0;
}
if (
(tmp->dez_op == DEZ_OP_IF && tmp->zop->opcode == ZEND_JMP) || /* if(false) */
tmp->dez_op == DEZ_OP_CASE || /* case */
dez_get_dest(tmp) >= ZEND_LINENUM(pzop)+2 /* the dest of parent is next node */
)
{
if (ZEND_GET_ORI(pzop) == ZEND_GET_ORI(tmp->zop)) /* is ZEND_JMP of default */
{
m_dez_op_current = dez_node_pop();
}
else
{
dez_exit_branch(0); //m_dez_op_current = dez_node_pop();
}
}
else
{
free(content);
free(node);
return 0;
}
}
if (parent->dez_op == DEZ_OP_BOOL)
{
if (
parent->zop->op1.op_type == IS_CONST &&
parent->zop->op1.u.constant.type == IS_BOOL &&
parent->zop->op1.u.constant.value.lval == 0
)
{
parent->dez_op = DEZ_OP_SWITCH;
swcontent = (DEZ_NODE_EXPR *)(parent->content);
branch = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
if (branch == NULL)
{
return -1;
}
branch->dez_op = DEZ_OP_NOP;
branch->zop = NULL;
branch->content = NULL;
branch->prev = NULL;
branch->next = NULL;
swcontent->branch_node = branch;
}
else
{
return -1;
}
}
else if (parent->dez_op == DEZ_OP_SWITCH)
{
branch = ((DEZ_NODE_EXPR *)(parent->content))->branch_node;
while(branch->next != NULL) branch = branch->next;
}
else
{
return -1;
}
content->op1_node = parent; /* pointer to switch node */
branch->next = node;
node->prev = branch;
m_dez_op_current= node;
return 1; /* enter default branch */
}
/*-- convertor for DEZ_OP_FUNCTION or DEZ_OP_CLASS --*/
static int dez_node_cvt_function_or_class (unsigned char dez_op, zend_op *pzop)
{
DEZ_NODE *node;
node = m_dez_op_root;
while(node != NULL)
{
if (pzop->extended_value == ZEND_DECLARE_FUNCTION)
{
if (node->dez_op == DEZ_OP_FUNCTION)
{
DEZ_NODE_FUNCTION *content;
content = (DEZ_NODE_FUNCTION *)(node->content);
if (0 == strcmp(content->name, pzop->op2.u.constant.value.str.val))
{
fetch_node(node);
DEZ_ADD_NODE(node);
return 0;
}
}
}
else if
(
pzop->extended_value == ZEND_DECLARE_CLASS ||
pzop->extended_value == ZEND_DECLARE_INHERITED_CLASS
) /* declare class */
{
if (node->dez_op == DEZ_OP_CLASS)
{
DEZ_NODE_CLASS *content;
content = (DEZ_NODE_CLASS *)(node->content);
if (0 == strcmp(content->name, pzop->op2.u.constant.value.str.val))
{
fetch_node(node);
DEZ_ADD_NODE(node);
return 0;
}
}
}
node = node->next;
}
return 0;
}
/*-- convertor for DEZ_OP_DOUBLE_ARROW --*/
static int dez_node_cvt_double_arrow (unsigned char dez_op, zend_op *pzop)
{
DEZ_NODE *node, *parent;
DEZ_NODE_DA *content;
content = (DEZ_NODE_DA *)malloc(sizeof(DEZ_NODE_DA));
if (content == NULL)
{
return -1;
}
node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
if (node == NULL)
{
free(content);
return -1;
}
parent = fetch_tmp_node(&(pzop->result));
content->branch_node = NULL;
content->key_node = fetch_tmp_node(&(pzop->op2));
content->value_node = fetch_tmp_node(&(pzop->op1));
content->next_node = parent;
if (parent != NULL) parent->prev = node;
node->dez_op = DEZ_OP_ARRAY;
node->zop = pzop;
node->content = content;
node->prev = NULL;
node->next = NULL;
DEZ_ADD_NODE(node);
return 0;
}
/*-- convertor for DEZ_OP_ARRAY --*/
static int dez_node_cvt_array (unsigned char dez_op, zend_op *pzop)
{
DEZ_NODE *node;
DEZ_NODE_DA *content;
content = (DEZ_NODE_DA *)malloc(sizeof(DEZ_NODE_DA));
if (content == NULL)
{
return -1;
}
node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
if (node == NULL)
{
free(content);
return -1;
}
content->branch_node = NULL;
content->key_node = fetch_tmp_node(&(pzop->op2));
content->value_node = fetch_tmp_node(&(pzop->op1));
content->next_node = NULL;
node->dez_op = dez_op;
node->zop = pzop;
node->content = content;
DEZ_ADD_NODE(node);
return 0;
}
/*-- convertor for DEZ_OP_HEREDOC --*/
static int dez_node_cvt_heredoc (unsigned char dez_op, zend_op *pzop)
{
/**********/
return 0;
}
/*-- convertor for DEZ_OP_DOLLAR_OPEN_CURLY_BRACES --*/
static int dez_node_cvt_dollar_open_curly_braces (unsigned char dez_op, zend_op *pzop)
{
/**********/
return 0;
}
/*-- convertor for DEZ_OP_CALL --*/
static int dez_node_cvt_call (unsigned char dez_op, zend_op *pzop)
{
DEZ_NODE *node, *param, *tmp;
DEZ_NODE_EXPR *content;
int param_num;
content = (DEZ_NODE_EXPR *)malloc(sizeof(DEZ_NODE_EXPR));
if (content == NULL)
{
return -1;
}
node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
if (node == NULL)
{
free(content);
return -1;
}
content->branch_node = NULL;
content->op1_node = fetch_call_ini_node(&(pzop->op1));
param = NULL;
tmp = m_dez_op_current;
param_num = pzop->extended_value;
while (tmp != NULL && param_num > 0)
{
DEZ_NODE *prev = tmp->prev;
if (tmp->dez_op == DEZ_OP_CALL_PARAM)
{
if (tmp == m_dez_op_current)
{
m_dez_op_current = prev;
}
if (tmp->prev != NULL)
{
tmp->prev->next = tmp->next;
tmp->prev = NULL;
}
if (tmp->next != NULL)
{
tmp->next->prev = prev;
tmp->next = NULL;
}
tmp->next = param;
param = tmp;
param_num--;
}
tmp = prev;
}
content->op2_node = param;
node->dez_op = dez_op;
node->zop = pzop;
node->content = content;
node->next = NULL;
if (pzop->opcode == ZEND_DO_FCALL_BY_NAME)
{
if (m_dez_op_current->dez_op == DEZ_OP_NEW)
{
content = (DEZ_NODE_EXPR *)(m_dez_op_current->content);
if (content->op1_node != NULL)
{
((DEZ_NODE_EXPR *)(node->content))->op1_node = content->op1_node;
}
content->op1_node = node;
return 0;
}
}
DEZ_ADD_NODE(node);
return 0;
}
/*-- convertor for DEZ_OP_BOOL --*/
static int dez_node_cvt_bool (unsigned char dez_op, zend_op *pzop)
{
DEZ_NODE *node, *tmp;
DEZ_NODE_EXPR *content;
if (
pzop->op1.op_type == IS_CONST &&
pzop->op1.u.constant.type == IS_BOOL &&
pzop->op1.u.constant.value.lval == 1 &&
ZEND_GET_ORI(pzop)[-1].opcode == ZEND_JMP
) /* default of switch */
{
return dez_node_cvt_default(DEZ_OP_DEFAULT, ZEND_GET_ORI(pzop)-1);
}
content = (DEZ_NODE_EXPR *)malloc(sizeof(DEZ_NODE_EXPR));
if (content == NULL)
{
return -1;
}
node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
if (node == NULL)
{
free(content);
return -1;
}
content->branch_node = NULL;
content->op1_node = NULL;
content->op2_node = NULL;
node->dez_op = dez_op;
node->zop = pzop;
node->content = content;
node->prev = NULL;
node->next = NULL;
tmp = fetch_tmp_node(&(pzop->result));
if (tmp == NULL)
{
DEZ_ADD_NODE(node);
return 0;
}
if (tmp->dez_op == DEZ_OP_LOGICAL_OR || tmp->dez_op == DEZ_OP_LOGICAL_AND)
{
content->op1_node = fetch_tmp_node(&(pzop->op1)); /* 2nd condition */
content->op2_node = tmp; /* 1st condition */
node->dez_op = tmp->dez_op;
DEZ_ADD_NODE(node);
return 0;
}
else
{
return -1;
}
}
static int dez_add_jmp_node(zend_op *pzop)
{
DEZ_NODE *node;
DEZ_NODE_EXPR *content;
content = (DEZ_NODE_EXPR *)malloc(sizeof(DEZ_NODE_EXPR));
if (content == NULL)
{
return -1;
}
node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
if (node == NULL)
{
free(content);
return -1;
}
content->branch_node = NULL;
content->op1_node = NULL;
content->op2_node = NULL;
node->dez_op = DEZ_OP_JMP;
node->zop = pzop;
node->content = content;
node->prev = NULL;
node->next = NULL;
DEZ_ADD_NODE(node);
return 0;
}
/*-- convertor for DEZ_OP_JMP --*/
static int dez_node_cvt_jmp (unsigned char dez_op, zend_op *pzop)
{
DEZ_NODE *parent;
int p_linenum;
parent = dez_node_get();
if (parent == NULL)
{
p_linenum = -1;
}
else
{
p_linenum = get_zend_linenum(parent);
}
if (ZEND_LINENUM(pzop) < (int)(pzop->op1.u.opline_num)) /* goto forward */
{
if (m_max_jmp_dest < pzop->op1.u.opline_num)
{
m_max_jmp_dest = pzop->op1.u.opline_num;
}
if (
parent != NULL &&
parent->dez_op == DEZ_OP_CASE
)
{
zend_op *dest;
dest = m_zend_op_start + pzop->op1.u.opline_num;
if (
(dest[-1].opcode == ZEND_JMPZ || dest[-1].opcode == ZEND_JMPZNZ) &&
dest[-2].opcode == ZEND_CASE
) /* the dest is 'case' */
{
dez_exit_branch(0); /* exit the case branch */
return 0;
}
else if (
dest[-1].opcode == ZEND_BOOL &&
dest[-2].opcode == ZEND_JMP
) /* the dest is 'default' */
{
dez_exit_branch(0); /* exit the case branch */
return 0;
}
}
return dez_node_cvt_if(DEZ_OP_IF, pzop); /* add if (false) node */
}
else /* goto afterware */
{
int header_linenum;
if (
parent != NULL && parent->dez_op == DEZ_OP_FOR &&
((DEZ_NODE_FOR *)(parent->content))->before_node != NULL
)
{
header_linenum = get_zend_linenum(((DEZ_NODE_FOR *)(parent->content))->before_node);
}
else
{
header_linenum = get_prev_zend_linenum(parent);
}
if ((int)(pzop->op1.u.opline_num) > p_linenum) /* within this branch */
{
DEZ_NODE *node, *branch;
DEZ_NODE_IF *content;
int dest;
if (
parent != NULL &&
parent->dez_op == DEZ_OP_FOR
)
{
DEZ_NODE_FOR *content;
content = (DEZ_NODE_FOR *)(parent->content);
if (content == NULL)
{
return -1;
}
if (
content->after_node != NULL &&
pzop->op1.u.opline_num <= get_zend_linenum(content->after_node)
)
{
return 0;
}
}
#if 0
else if (
parent != NULL &&
parent->dez_op == DEZ_OP_FOREACH
)
{
DEZ_NODE *dest;
if (pzop->op1.u.opline_num == p_linenum+1)
{
return 2; /* exit foreach branch */
}
}
#endif
content = (DEZ_NODE_IF *)malloc(sizeof(DEZ_NODE_IF));
if (content == NULL)
{
return -1;
}
node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
if (node == NULL)
{
free(content);
return -1;
}
branch = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
if (branch == NULL)
{
return -1;
}
branch->dez_op = DEZ_OP_NOP;
branch->zop = NULL;
branch->content = NULL;
branch->prev = NULL;
branch->next = fetch_jmp_dest_node(pzop->op1.u.opline_num);
if (branch->next != NULL) branch->next->prev = branch;
content->branch_node = branch;
content->op1_node = NULL;
content->op2_node = NULL;
content->dest = ZEND_LINENUM(pzop);
node->dez_op = DEZ_OP_WHILE;
node->zop = pzop;/*branch->next->zop;*/
node->content = content;
node->prev = NULL;
node->next = NULL;
dest = dez_get_branch_end(parent);
// dez_node_cvt_if(DEZ_OP_IF, pzop); /* add if (false) */
clear_or_recover_zend_op(ZEND_GET_ORI(pzop)+1, dest-ZEND_LINENUM(pzop)-1, 1); /* recover the remainder opcodes in this branch */
DEZ_ADD_NODE(node); /* add while (true) */
return 0;
}
else if (
(int)(pzop->op1.u.opline_num) <= p_linenum &&
(int)(pzop->op1.u.opline_num) > header_linenum
) /* the dest is the header of this branch */
{
int dest;
if (parent == NULL)
{
return 0;
}
dest = dez_get_branch_end(parent);
if (parent->dez_op == DEZ_OP_IF)
{
DEZ_NODE *pp;
int n = dest-ZEND_LINENUM(pzop)-1;
if (parent->zop->opcode != ZEND_JMP) /* not if (false) */
{
parent->dez_op = DEZ_OP_WHILE;
}
if (dez_in_branch(parent, DEZ_OP_CASE) == 0) /* the while() is in case branch */
{
int i;
zend_op *zp = ZEND_GET_ORI(pzop)+1;
i = 0;
while(i < n)
{
if (
(
zp[i].opcode == ZEND_JMP &&
zp[i+1].opcode == ZEND_BOOL
) || /* default node */
(
zp[i].opcode == ZEND_CASE &&
(zp[i+1].opcode == ZEND_JMPZ || zp[i+1].opcode == ZEND_JMPZNZ)
) /* case node */
)
{
break;
}
i++;
}
if (i < n) /* the case or default node was found */
{
zend_op *dupzop;
dupzop = dez_dup_zend_op(pzop);
dupzop->op1.u.opline_num = dest;
// dez_node_cvt_jmp(DEZ_OP_JMP, dupzop); /* add if (false) */
n = i;
}
}
clear_or_recover_zend_op(ZEND_GET_ORI(pzop)+1, n, 0); /* clear the remainder opcodes in this branch */
dez_node_cvt_if(DEZ_OP_IF, pzop); /* add if (false) */
dez_exit_branch(0); /* exit the branch */
return 0;
}
else if (parent->dez_op == DEZ_OP_FOR)
{
DEZ_NODE_FOR *content;
content = (DEZ_NODE_FOR *)(parent->content);
if (content == NULL)
{
return -1;
}
if (content->after_node == NULL)
{
content->after_node = fetch_jmp_dest_node(pzop->op1.u.opline_num);
}
else if (pzop->op1.u.opline_num == get_zend_linenum(content->after_node))
{
clear_or_recover_zend_op(ZEND_GET_ORI(pzop)+1, dest-ZEND_LINENUM(pzop)-1, 0); /* clear the remainder opcodes in this branch */
dez_node_cvt_if(DEZ_OP_IF, pzop); /* add if (false) */
dez_exit_branch(0); /* exit the branch */
// return dez_node_specs[DEZ_OP_CONTINUE].dez_node_cvt_func (DEZ_OP_CONTINUE, pzop); /* add continue node */
}
return 0;
}
else if (parent->dez_op == DEZ_OP_FOREACH)
{
clear_or_recover_zend_op(ZEND_GET_ORI(pzop)+1, dest-ZEND_LINENUM(pzop)-1, 0); /* clear the remainder opcodes in this branch */
dez_node_cvt_if(DEZ_OP_IF, pzop); /* add if (false) */
// return dez_node_specs[DEZ_OP_CONTINUE].dez_node_cvt_func (DEZ_OP_CONTINUE, pzop); /* add continue node */
}
return 0;
}
else /* the dest is without this branch */
{
int dest;
zend_op *prev_zop;
dest = dez_get_branch_end(parent);
clear_or_recover_zend_op(ZEND_GET_ORI(pzop)+1, dest-ZEND_LINENUM(pzop)-1, 0); /* clear the remainder opcodes in this branch */
dest = dez_get_dest(parent); // dez_get_branch_end(parent);
if (
dest > ZEND_LINENUM(pzop) && /* jump foreward away */
parent != NULL &&
parent->dez_op == DEZ_OP_ELSE
) /* break? */
{
DEZ_NODE_EXPR *c;
dez_exit_branch(0); /* exit this branch */
/*-- fetch the sub branch and add them into m_dez_op_current --*/
c = (DEZ_NODE_EXPR *)(parent->content);
if (c != NULL && c->branch_node != NULL) /* the sub branch is exist */
{
m_dez_op_current->next = c->branch_node->next;
if (c->branch_node->next != NULL) c->branch_node->next->prev = m_dez_op_current;
free(c->branch_node);
c->branch_node = NULL;
while(m_dez_op_current->next != NULL) m_dez_op_current = m_dez_op_current->next;
}
DEZ_DEL_NODE(parent); /* remove the else node */
return dez_node_cvt_jmp(DEZ_OP_JMP, pzop);
}
prev_zop = ZEND_GET_ORI(pzop)-1;
if (
m_dez_op_current->dez_op == DEZ_OP_WHILE && m_dez_op_current->zop->opcode == ZEND_JMP && /* the previous node is while(true) */
prev_zop->opcode == ZEND_JMP &&
(int)(prev_zop->op1.u.opline_num) <= p_linenum && /* jmp to header */
(int)(prev_zop->op1.u.opline_num) > header_linenum /* ------------- */
)
{
/* do nothing */
}
else
{
dez_node_cvt_if(DEZ_OP_IF, pzop); /* add if (false) node */
}
dez_exit_branch(1); /* exit this branch */
return 0;
}
}
return dez_node_cvt_expr (dez_op, pzop); /* add jmp node */
}
/*-- convertor for DEZ_OP_FUNC_PARAM --*/
static int dez_node_cvt_func_param (unsigned char dez_op, zend_op *pzop)
{
static char paramname[1024];
DEZ_NODE *node, *parent, *param;
DEZ_NODE_EXPR *content;
DEZ_NODE_FUNCTION *funcc;
parent = dez_node_get();
if (parent == NULL)
{
return -1;
}
if (parent->dez_op != DEZ_OP_FUNCTION)
{
return -1;
}
funcc = (DEZ_NODE_FUNCTION *)(parent->content);
if (funcc == NULL)
{
return -1;
}
content = (DEZ_NODE_EXPR *)malloc(sizeof(DEZ_NODE_EXPR));
if (content == NULL)
{
return -1;
}
node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
if (node == NULL)
{
free(content);
return -1;
}
content->branch_node = NULL;
content->op1_node = fetch_tmp_node(&(pzop->result));
#if 0
if (content->op1_node == NULL)
{
sprintf(paramname, "dez_param_%u", pzop->result.u.var);
dez_add_var(pzop->result.u.var, paramname, strlen(paramname));
}
#endif
if (pzop->opcode == ZEND_RECV_INIT)
{
content->op2_node = fetch_tmp_node(&(pzop->op2));
}
else
{
content->op2_node = NULL;
}
node->dez_op = dez_op;
node->zop = pzop;
node->content = content;
node->prev = NULL;
node->next = NULL;
param = funcc->param_node;
if (param == NULL)
{
funcc->param_node = node;
}
else
{
while(param->next != NULL)
{
param = param->next;
}
param->next = node;
node->prev = param;
}
return 0;
}
/*-- convertor for DEZ_OP_UNKNOWN --*/
static int dez_node_cvt_unknown (unsigned char dez_op, zend_op *pzop)
{
/**********/
return 0;
}
static int dez_node_output_nop(DEZ_NODE *pdez_node)
{
/******************/
return 0;
}
static int dez_node_output_expr(DEZ_NODE *pdez_node)
{
DEZ_NODE_EXPR *content;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_EXPR *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
if (
pdez_node->dez_op == DEZ_OP_BW_NOT || /* ~ */
pdez_node->dez_op == DEZ_OP_BOOL_NOT /* ! */
)
{
printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
if (content->op1_node != NULL)
{
dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op1), 1);
}
}
else if (
pdez_node->dez_op == DEZ_OP_CONCAT &&
pdez_node->zop->opcode == ZEND_ADD_CHAR
)
{
printf ( "(");
if (content->op1_node != NULL)
{
dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op1), 1);
}
printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
if (content->op2_node != NULL)
{
dez_node_specs[content->op2_node->dez_op].dez_node_output_func (content->op2_node);
}
else
{
printf ( "'%c'", (char)(pdez_node->zop->op2.u.constant.value.lval));
}
printf ( ")");
}
else
{
if (
pdez_node->dez_op != DEZ_OP_OBJECT_OPERATOR
)
{
printf ( "(");
}
if (content->op1_node != NULL)
{
dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op1), 1);
}
printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
if (content->op2_node != NULL)
{
dez_node_specs[content->op2_node->dez_op].dez_node_output_func (content->op2_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op2), (pdez_node->dez_op == DEZ_OP_OBJECT_OPERATOR ? 0: 1));
}
if (
pdez_node->dez_op != DEZ_OP_OBJECT_OPERATOR
)
{
printf ( ")");
}
}
return 0;
}
static int dez_node_output_cast(DEZ_NODE *pdez_node)
{
static char *dez_cast_str[] =
{
"(unset)",
"(int)",
"(double)",
"(string)",
"(array)",
"(object)",
"(bool)"
};
DEZ_NODE_EXPR *content;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_EXPR *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
printf ("%s", dez_cast_str[pdez_node->zop->extended_value]);
if (content->op1_node != NULL)
{
dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op1), 1);
}
return 0;
}
static int dez_node_output_qm_assign(DEZ_NODE *pdez_node)
{
DEZ_NODE_EXPR *content;
DEZ_NODE *qm_true;
DEZ_NODE_EXPR *content1;
DEZ_NODE *qm_cond;
DEZ_NODE_EXPR *content2;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_EXPR *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
qm_true = content->op2_node;
if (qm_true == NULL)
{
return -1;
}
content1 = (DEZ_NODE_EXPR *)(qm_true->content);
if (content1 == NULL)
{
return -1;
}
printf ( "(");
qm_cond = content1->op2_node;
if (qm_cond == NULL)
{
printf ("true");
}
else
{
content2 = (DEZ_NODE_EXPR *)(qm_cond->content);
if (content2 == NULL)
{
return -1;
}
if (qm_cond->zop->opcode == ZEND_JMP)
{
printf ("false");
}
else if (content2->op1_node != NULL)
{
dez_node_specs[content2->op1_node->dez_op].dez_node_output_func (content2->op1_node);
}
else
{
dez_dump_znode(&(qm_cond->zop->op1), 1);
}
}
printf ( " ? ");
if (content1->op1_node != NULL)
{
dez_node_specs[content1->op1_node->dez_op].dez_node_output_func (content1->op1_node);
}
else
{
dez_dump_znode(&(qm_true->zop->op1), 1);
}
printf ( " : ");
if (content->op1_node != NULL)
{
dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op1), 1);
}
printf ( ")");
return 0;
}
static int dez_node_output_pre(DEZ_NODE *pdez_node)
{
DEZ_NODE_EXPR *content;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_EXPR *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
if (content->op1_node != NULL)
{
dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op1), (pdez_node->dez_op == DEZ_OP_FETCH ? 0 : 1));
}
return 0;
}
static int dez_node_output_pre2(DEZ_NODE *pdez_node)
{
DEZ_NODE_IF *content;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_IF *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
if (pdez_node->dez_op == DEZ_OP_BREAK)
{
if (pdez_node->zop->opcode == ZEND_BRK)
{
if (
pdez_node->zop->op2.op_type == IS_CONST &&
pdez_node->zop->op2.u.constant.type == IS_LONG &&
pdez_node->zop->op2.u.constant.value.lval == 1
)
{
/* do nothing */
}
else
{
printf (" ");
if (content->op2_node != NULL)
{
dez_node_specs[content->op2_node->dez_op].dez_node_output_func (content->op2_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op2), 1);
}
}
}
else /* ZEND_JMP */
{
if (content->dest > 1)
{
printf (" %u", content->dest);
}
}
}
return 0;
}
static int dez_node_output_post(DEZ_NODE *pdez_node)
{
DEZ_NODE_EXPR *content;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_EXPR *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
if (content->op1_node != NULL)
{
dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op1), 1);
}
printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
return 0;
}
static int dez_node_output_assign(DEZ_NODE *pdez_node)
{
DEZ_NODE_EXPR *content;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_EXPR *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
if (content->op1_node != NULL)
{
dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op1), 1);
}
printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
if (content->op2_node != NULL)
{
dez_node_specs[content->op2_node->dez_op].dez_node_output_func (content->op2_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op2), 1);
}
return 0;
}
static int dez_node_output_assign_ref(DEZ_NODE *pdez_node)
{
DEZ_NODE_EXPR *content;
zend_op *zop;
zval **tmp;
TSRMLS_FETCH();
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_EXPR *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
if (content->op2_node != NULL)
{
zop = content->op2_node->zop;
if (zop->opcode == ZEND_FETCH_W && zop->op2.u.fetch_type == ZEND_FETCH_STATIC) /* static variable */
{
zend_op_array *op_array;
printf ( "static ");
if (content->op1_node != NULL)
{
dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op1), 1);
}
/*
dez_add_var (pdez_node->zop->op1.u.var, zop->op1.u.constant.value.str.val, zop->op1.u.constant.value.str.len);
printf ( "static %s", dez_get_varname(&(pdez_node->zop->op1)));
*/
if (m_current_function == NULL) /* main branch */
{
op_array = EG(active_op_array);
}
else
{
op_array = ((DEZ_NODE_FUNCTION *)(m_current_function->content))->op_array;
}
tmp = NULL;
zend_hash_find(op_array->static_variables, zop->op1.u.constant.value.str.val, zop->op1.u.constant.value.str.len+1, (void **)&tmp);
if (tmp != NULL) /* init value assigned */
{
printf ( " = ");
dez_dump_zval(**tmp, 1);
}
return 0;
}
else if (zop->opcode == ZEND_FETCH_W && zop->op2.u.fetch_type == ZEND_FETCH_GLOBAL) /* global variable */
{
printf ( "global ");
if (content->op1_node != NULL)
{
dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op1), 1);
}
/*
dez_add_var (pdez_node->zop->op1.u.var, zop->op1.u.constant.value.str.val, zop->op1.u.constant.value.str.len);
printf ( "global %s", dez_get_varname(&(pdez_node->zop->op1)));
*/
return 0;
}
#if 0
else if (zop->opcode == ZEND_FETCH_W && zop->op2.u.fetch_type == ZEND_FETCH_LOCAL) /* local variable */
{
dez_add_var (pdez_node->zop->op1.u.var, zop->op1.u.constant.value.str.val, zop->op1.u.constant.value.str.len);
printf ( "%s", dez_get_varname(&(pdez_node->zop->op1)));
return 0;
}
#endif
}
/*-- a = &b --*/
if (content->op1_node != NULL)
{
dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op1), 1);
}
printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
if (content->op2_node != NULL)
{
dez_node_specs[content->op2_node->dez_op].dez_node_output_func (content->op2_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op2), 1);
}
return 0;
}
static int dez_node_output_include_or_eval(DEZ_NODE *pdez_node)
{
DEZ_NODE_EXPR *content;
char *str;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_EXPR *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
switch (pdez_node->zop->op2.u.constant.value.lval)
{
case ZEND_EVAL:
str = "eval (";
break;
case ZEND_INCLUDE:
str = "include ";
break;
case ZEND_INCLUDE_ONCE:
str = "include_once ";
break;
case ZEND_REQUIRE:
str = "require ";
break;
case ZEND_REQUIRE_ONCE:
str = "require_once ";
break;
}
printf ( str);
if (content->op1_node != NULL)
{
dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op1), 1);
}
if (pdez_node->zop->op2.u.constant.value.lval == ZEND_EVAL)
{
printf ( ")");
}
return 0;
}
static int dez_node_output_or_and(DEZ_NODE *pdez_node)
{
DEZ_NODE_EXPR *content;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_EXPR *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
printf ( "(");
if (content->op2_node != NULL)
{
DEZ_NODE_EXPR *cond1 = (DEZ_NODE_EXPR *)(content->op2_node->content);
if (cond1->op1_node != NULL)
{
dez_node_specs[cond1->op1_node->dez_op].dez_node_output_func (cond1->op1_node);
}
else
{
dez_dump_znode(&(content->op2_node->zop->op1), 1);
}
}
printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
if (content->op1_node != NULL)
{
dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op1), 1);
}
printf ( ")");
return 0;
}
static int dez_node_output_new(DEZ_NODE *pdez_node)
{
DEZ_NODE_EXPR *content;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_EXPR *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
if (content->op1_node != NULL)
{
dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op1), 1);
/*
switch(pdez_node->zop->op1.op_type)
{
case IS_CONST:
printf ("%s", pdez_node->zop->op1.u.constant.value.str.val);
break;
case 16:
printf ("%s", dez_get_varname(&(pdez_node->zop->op1)));
break;
}
*/
}
return 0;
}
static int dez_node_output_exit(DEZ_NODE *pdez_node)
{
DEZ_NODE_EXPR *content;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_EXPR *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
printf ( "exit (");
if (content->op1_node != NULL)
{
dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op1), 1);
}
printf ( ")");
return 0;
}
static int dez_node_output_if(DEZ_NODE *pdez_node)
{
DEZ_NODE_EXPR *content;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_EXPR *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
printf ( "(");
if (pdez_node->zop->opcode == ZEND_JMP)
{
printf ( (pdez_node->dez_op == DEZ_OP_WHILE ? "true" : "false"));
}
else
{
if (content->op1_node != NULL)
{
dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op1), 1);
}
}
printf ( ")");
return 0;
}
static int dez_node_output_do(DEZ_NODE *pdez_node)
{
printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
return 0;
}
static int dez_node_output_for(DEZ_NODE *pdez_node)
{
DEZ_NODE *node;
DEZ_NODE_FOR *content;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_FOR *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
printf ( "(");
if (content->before_node != NULL)
{
dez_node_specs[content->before_node->dez_op].dez_node_output_func (content->before_node);
}
printf ( "; ");
if (content->cond_node != NULL)
{
dez_node_specs[content->cond_node->dez_op].dez_node_output_func (content->cond_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op1), 1);
}
printf ( "; ");
node = content->after_node;
while (node != NULL)
{
dez_node_specs[node->dez_op].dez_node_output_func (node);
node = node->next;
if (node != NULL)
{
printf ( ", ");
}
}
printf ( ")");
return 0;
}
static int dez_node_output_foreach(DEZ_NODE *pdez_node)
{
DEZ_NODE *node;
DEZ_NODE_FOREACH *content;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_FOREACH *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
printf ( "(");
if (content->source_node != NULL)
{
dez_node_specs[content->source_node->dez_op].dez_node_output_func (content->source_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op1), 1);
}
printf ( " as ");
if (content->key_node != NULL)
{
dez_node_specs[content->key_node->dez_op].dez_node_output_func (content->key_node);
printf ("%s", dez_node_specs[DEZ_OP_DOUBLE_ARROW].desc);
}
if (content->value_node != NULL)
{
dez_node_specs[content->value_node->dez_op].dez_node_output_func (content->value_node);
}
printf ( ")");
return 0;
}
static int dez_node_output_declare(DEZ_NODE *pdez_node)
{
DEZ_NODE_EXPR *content;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_EXPR *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
printf ( "(");
if (pdez_node->zop->opcode == ZEND_TICKS)
{
printf ( "ticks = ");
dez_dump_znode(&(pdez_node->zop->op1), 1);
}
printf ( ")");
return 0;
}
static int dez_node_output_case(DEZ_NODE *pdez_node)
{
DEZ_NODE_EXPR *content;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_EXPR *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
if (content->op2_node != NULL)
{
dez_node_specs[content->op2_node->dez_op].dez_node_output_func (content->op2_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op2), 1);
}
printf ( ":");
return 0;
}
static int dez_node_output_default(DEZ_NODE *pdez_node)
{
printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
return 0;
}
static int dez_node_output_function(DEZ_NODE *pdez_node)
{
DEZ_NODE *node;
DEZ_NODE_FUNCTION *content;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_FUNCTION *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
printf ("%s", content->name);
printf ( " (");
for (node = content->param_node; node != NULL; node = node->next)
{
if (
content->op_array != NULL &&
content->op_array->arg_types != NULL &&
content->op_array->arg_types[node->zop->op1.u.constant.value.lval] == BYREF_FORCE
)
{
printf ("&");
}
dez_node_specs[node->dez_op].dez_node_output_func (node);
if (node->next != NULL)
{
printf ( ", ");
}
}
printf ( ")");
return 0;
}
static int dez_node_output_var(DEZ_NODE *pdez_node)
{
DEZ_NODE_VAR *content;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_VAR *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
if (content->property != NULL)
{
printf ("$%s", content->property->arKey);
if (content->property->pData != NULL)
{
printf ( " = ");
dez_dump_zval(**((zval **)(content->property->pData)), 1);
}
}
return 0;
}
static int dez_node_output_unset(DEZ_NODE *pdez_node)
{
DEZ_NODE_EXPR *content;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_EXPR *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
printf ( "($");
if (content->op1_node != NULL)
{
dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op1), 0);
}
printf ( ")");
return 0;
}
static int dez_node_output_isset_or_empty(DEZ_NODE *pdez_node)
{
DEZ_NODE_EXPR *content;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_EXPR *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
if (pdez_node->zop->op2.u.constant.value.lval == 1)
{
printf ("%s", dez_node_specs[DEZ_OP_ISSET].desc);
}
else
{
printf ("%s", dez_node_specs[DEZ_OP_EMPTY].desc);
}
printf ( "(");
if (content->op1_node != NULL)
{
dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op1), 1);
}
printf ( ")");
return 0;
}
static int dez_node_output_class(DEZ_NODE *pdez_node)
{
DEZ_NODE *node;
DEZ_NODE_CLASS *content;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_CLASS *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
printf ("%s", content->name);
if (content->parent != NULL)
{
printf ( " extends %s", content->parent->name);
}
return 0;
}
static int dez_node_output_double_arrow(DEZ_NODE *pdez_node)
{
DEZ_NODE *node;
DEZ_NODE_DA *content;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_DA *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
if (content->next_node != NULL) /* is not the first element */
{
dez_node_output_double_arrow(content->next_node);
printf ( ", ");
}
if (pdez_node->zop->op2.op_type != IS_UNUSED)
{
if (content->key_node != NULL)
{
dez_node_specs[content->key_node->dez_op].dez_node_output_func (content->key_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op2), 1);
}
printf ("%s", dez_node_specs[DEZ_OP_DOUBLE_ARROW].desc);
}
if (content->value_node != NULL)
{
if (content->value_node->zop->opcode == ZEND_FETCH_W) /* refrence variable */
{
printf ( "&");
}
dez_node_specs[content->value_node->dez_op].dez_node_output_func (content->value_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op1), 1);
}
return 0;
}
static int dez_node_output_list(DEZ_NODE *pdez_node)
{
DEZ_NODE_LIST *lc;
DEZ_NODE *le;
if (pdez_node == NULL)
{
return -1;
}
lc = (DEZ_NODE_LIST *)(pdez_node->content);
if (lc == NULL)
{
return -1;
}
printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
printf ( "(");
le = lc->le_node;
while (le != NULL)
{
dez_node_specs[le->dez_op].dez_node_output_func (le);
le = le->next;
if (le != NULL)
{
printf ( ", ");
}
}
printf ( ")");
if (lc->dest_node != NULL)
{
DEZ_NODE *last_fetch, *next;
DEZ_NODE_EXPR *dc = (DEZ_NODE_EXPR *)(lc->dest_node->content);
last_fetch = lc->dest_node;
while (last_fetch != NULL)
{
next = ((DEZ_NODE_EXPR *)(last_fetch->content))->op1_node;
if (
next == NULL ||
next->dez_op != DEZ_OP_FETCH_DIM
)
{
break;
}
last_fetch = next;
}
if (
last_fetch != NULL &&
(
((DEZ_NODE_EXPR *)(last_fetch->content))->op1_node != NULL ||
(last_fetch->zop->op1.op_type != IS_TMP_VAR && last_fetch->zop->op1.op_type != IS_VAR)
)
)
{
printf ("%s", dez_node_specs[DEZ_OP_ASSIGN].desc);
if (dc->op1_node != NULL)
{
dez_node_specs[dc->op1_node->dez_op].dez_node_output_func (dc->op1_node);
}
else
{
dez_dump_znode(&(lc->dest_node->zop->op1), 1);
}
}
}
return 0;
}
static int dez_node_output_le(DEZ_NODE *pdez_node)
{
DEZ_NODE_LE *lec;
if (pdez_node == NULL)
{
return -1;
}
lec = (DEZ_NODE_LE *)(pdez_node->content);
if (lec == NULL)
{
return -1;
}
if (lec->a_node != NULL)
{
if (lec->a_node->dez_op == DEZ_OP_LIST)
{
dez_node_specs[lec->a_node->dez_op].dez_node_output_func (lec->a_node);
}
else if (lec->a_node->dez_op == DEZ_OP_ASSIGN)
{
DEZ_NODE_EXPR *ac = (DEZ_NODE_EXPR *)(lec->a_node->content);
if (ac->op1_node != NULL)
{
dez_node_specs[ac->op1_node->dez_op].dez_node_output_func (ac->op1_node);
}
else
{
dez_dump_znode(&(lec->a_node->zop->op1), 1);
}
}
}
return 0;
}
static int dez_node_output_array(DEZ_NODE *pdez_node)
{
DEZ_NODE_DA *content;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_DA *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
printf ( "(");
pdez_node->dez_op = DEZ_OP_DOUBLE_ARROW;
dez_node_output_double_arrow(pdez_node);
pdez_node->dez_op = DEZ_OP_ARRAY;
printf ( ")");
return 0;
}
static int dez_node_output_heredoc(DEZ_NODE *pdez_node)
{
/******************/
return 0;
}
static int dez_node_output_dollar_open_curly_braces(DEZ_NODE *pdez_node)
{
/******************/
return 0;
}
static int dez_node_output_call_param(DEZ_NODE *pdez_node)
{
DEZ_NODE_EXPR *content;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_EXPR *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
if (pdez_node->zop->opcode == ZEND_SEND_REF)
{
printf ( "&");
}
if (content->op1_node != NULL)
{
dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op1), 1);
}
return 0;
}
static int dez_node_output_call_init(DEZ_NODE *pdez_node)
{
DEZ_NODE_EXPR *content;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_EXPR *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
if (pdez_node->zop->op1.op_type != IS_UNUSED)
{
if (content->op1_node != NULL)
{
dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
printf ( "->");
}
else
{
dez_dump_znode(&(pdez_node->zop->op1), 0);
if (
pdez_node->zop->op1.op_type == IS_CONST &&
pdez_node->zop->op1.u.constant.type == IS_STRING
) /* class method calling */
{
printf ( "::");
}
else
{
printf ( "->");
}
}
}
if (content->op2_node != NULL)
{
dez_node_specs[content->op2_node->dez_op].dez_node_output_func (content->op2_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op2), 0);
}
return 0;
}
static int dez_node_output_call(DEZ_NODE *pdez_node)
{
DEZ_NODE_EXPR *content;
DEZ_NODE *param;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_EXPR *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
if (content->op1_node != NULL)
{
dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op1), 0);
}
printf ( " (");
for (param = content->op2_node; param != NULL; param = param->next)
{
dez_node_specs[param->dez_op].dez_node_output_func (param);
if (param->next != NULL)
{
printf ( ", ");
}
}
printf ( ")");
return 0;
}
static int dez_node_output_call_ex(DEZ_NODE *pdez_node)
{
DEZ_NODE_EXPR *content;
DEZ_NODE *param;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_EXPR *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
printf ("%s", dez_get_funcname(&(pdez_node->zop->op1)));
printf ( " (");
for (param = content->op2_node; param != NULL; param = param->next)
{
dez_node_specs[param->dez_op].dez_node_output_func (param);
if (param->next != NULL)
{
printf ( ", ");
}
}
printf ( ")");
return 0;
}
static int dez_node_output_fetch_dim(DEZ_NODE *pdez_node)
{
DEZ_NODE_EXPR *content;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_EXPR *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
if (content->op1_node != NULL)
{
dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op1), 1);
}
printf ( "[");
if (content->op2_node != NULL)
{
dez_node_specs[content->op2_node->dez_op].dez_node_output_func (content->op2_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op2), 1);
}
printf ( "]");
return 0;
}
static int dez_node_output_init_string(DEZ_NODE *pdez_node)
{
printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
return 0;
}
static int dez_node_output_fetch_constant(DEZ_NODE *pdez_node)
{
dez_dump_znode(&(pdez_node->zop->op1), 0);
return 0;
}
static int dez_node_output_func_param(DEZ_NODE *pdez_node)
{
DEZ_NODE_EXPR *content;
if (pdez_node == NULL)
{
return -1;
}
content = (DEZ_NODE_EXPR *)(pdez_node->content);
if (content == NULL)
{
return -1;
}
printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
if (content->op1_node != NULL)
{
dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->result), 1);
}
if (pdez_node->zop->opcode == ZEND_RECV_INIT)
{
printf ( " = ");
if (content->op2_node != NULL)
{
dez_node_specs[content->op2_node->dez_op].dez_node_output_func (content->op2_node);
}
else
{
dez_dump_znode(&(pdez_node->zop->op2), 1);
}
}
return 0;
}
static int dez_node_output_unknown(DEZ_NODE *pdez_node)
{
/******************/
return 0;
}
/*-- free all dez nodes --*/
static void dez_node_free (void)
{
if (m_dez_op_root != NULL)
{
dez_node_specs[m_dez_op_root->dez_op].dez_node_free_func(m_dez_op_root);
m_dez_op_root = NULL;
}
}
/*-- free function for DEZ_NODE_NOP node --*/
static void dez_node_free_nop (DEZ_NODE *pdez_node)
{
if (pdez_node == NULL)
{
return;
}
/*-- free the next node --*/
if (pdez_node->next != NULL)
{
dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
}
/*-- free the node content --*/
if (pdez_node->content != NULL)
{
/**********/
free(pdez_node->content);
}
/*-- free the node self */
free(pdez_node);
}
static void dez_node_free_expr (DEZ_NODE *pdez_node)
{
DEZ_NODE_EXPR *content;
if (pdez_node == NULL)
{
return;
}
/*-- free the next node --*/
if (pdez_node->next != NULL)
{
dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
}
/*-- free the node content --*/
content = (DEZ_NODE_EXPR *)(pdez_node->content);
if (content != NULL)
{
if (content->branch_node) dez_node_specs[content->branch_node->dez_op].dez_node_free_func(content->branch_node);
if (content->op1_node) dez_node_specs[content->op1_node->dez_op].dez_node_free_func(content->op1_node);
if (content->op2_node) dez_node_specs[content->op2_node->dez_op].dez_node_free_func(content->op2_node);
free(content);
}
/*-- free the node self */
free(pdez_node);
}
static void dez_node_free_if (DEZ_NODE *pdez_node)
{
DEZ_NODE_IF *content;
if (pdez_node == NULL)
{
return;
}
/*-- free the next node --*/
if (pdez_node->next != NULL)
{
dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
}
/*-- free the node content --*/
content = (DEZ_NODE_IF *)(pdez_node->content);
if (content != NULL)
{
if (content->branch_node) dez_node_specs[content->branch_node->dez_op].dez_node_free_func(content->branch_node);
if (content->op1_node) dez_node_specs[content->op1_node->dez_op].dez_node_free_func(content->op1_node);
if (content->op2_node) dez_node_specs[content->op2_node->dez_op].dez_node_free_func(content->op2_node);
free(content);
}
/*-- free the node self */
free(pdez_node);
}
static void dez_node_free_for (DEZ_NODE *pdez_node)
{
DEZ_NODE_FOR *content;
if (pdez_node == NULL)
{
return;
}
/*-- free the next node --*/
if (pdez_node->next != NULL)
{
dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
}
/*-- free the node content --*/
content = (DEZ_NODE_FOR *)(pdez_node->content);
if (content != NULL)
{
if (content->branch_node) dez_node_specs[content->branch_node->dez_op].dez_node_free_func(content->branch_node);
if (content->before_node) dez_node_specs[content->before_node->dez_op].dez_node_free_func(content->before_node);
if (content->cond_node) dez_node_specs[content->cond_node->dez_op].dez_node_free_func(content->cond_node);
if (content->after_node) dez_node_specs[content->after_node->dez_op].dez_node_free_func(content->after_node);
free(content);
}
/*-- free the node self */
free(pdez_node);
}
static void dez_node_free_foreach (DEZ_NODE *pdez_node)
{
DEZ_NODE_FOREACH *content;
if (pdez_node == NULL)
{
return;
}
/*-- free the next node --*/
if (pdez_node->next != NULL)
{
dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
}
/*-- free the node content --*/
content = (DEZ_NODE_FOREACH *)(pdez_node->content);
if (content != NULL)
{
if (content->branch_node) dez_node_specs[content->branch_node->dez_op].dez_node_free_func(content->branch_node);
if (content->source_node) dez_node_specs[content->source_node->dez_op].dez_node_free_func(content->source_node);
if (content->key_node) dez_node_specs[content->key_node->dez_op].dez_node_free_func(content->key_node);
if (content->value_node) dez_node_specs[content->value_node->dez_op].dez_node_free_func(content->value_node);
free(content);
}
/*-- free the node self */
free(pdez_node);
}
static void dez_node_free_case (DEZ_NODE *pdez_node)
{
DEZ_NODE_EXPR *content;
if (pdez_node == NULL)
{
return;
}
/*-- free the next node --*/
if (pdez_node->next != NULL)
{
dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
}
/*-- free the node content --*/
content = (DEZ_NODE_EXPR *)(pdez_node->content);
if (content != NULL)
{
if (content->branch_node) dez_node_specs[content->branch_node->dez_op].dez_node_free_func(content->branch_node);
if (content->op2_node) dez_node_specs[content->op2_node->dez_op].dez_node_free_func(content->op2_node);
free(content);
}
/*-- free the node self */
free(pdez_node);
}
static void dez_node_free_default (DEZ_NODE *pdez_node)
{
DEZ_NODE_EXPR *content;
if (pdez_node == NULL)
{
return;
}
/*-- free the next node --*/
if (pdez_node->next != NULL)
{
dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
}
/*-- free the node content --*/
content = (DEZ_NODE_EXPR *)(pdez_node->content);
if (content != NULL)
{
if (content->branch_node) dez_node_specs[content->branch_node->dez_op].dez_node_free_func(content->branch_node);
free(content);
}
/*-- free the node self */
free(pdez_node);
}
static void dez_node_free_function (DEZ_NODE *pdez_node)
{
DEZ_NODE_FUNCTION *content;
if (pdez_node == NULL)
{
return;
}
/*-- free the next node --*/
if (pdez_node->next != NULL)
{
dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
}
/*-- free the node content --*/
content = (DEZ_NODE_FUNCTION *)(pdez_node->content);
if (content != NULL)
{
if (content->branch_node) dez_node_specs[content->branch_node->dez_op].dez_node_free_func(content->branch_node);
if (content->param_node) dez_node_specs[content->param_node->dez_op].dez_node_free_func(content->param_node);
free(content);
}
/*-- free the node self */
free(pdez_node);
}
static void dez_node_free_var (DEZ_NODE *pdez_node)
{
DEZ_NODE_VAR *content;
if (pdez_node == NULL)
{
return;
}
/*-- free the next node --*/
if (pdez_node->next != NULL)
{
dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
}
/*-- free the node content --*/
content = (DEZ_NODE_VAR *)(pdez_node->content);
if (content != NULL)
{
if (content->branch_node) dez_node_specs[content->branch_node->dez_op].dez_node_free_func(content->branch_node);
free(content);
}
/*-- free the node self */
free(pdez_node);
}
static void dez_node_free_class (DEZ_NODE *pdez_node)
{
DEZ_NODE_CLASS *content;
if (pdez_node == NULL)
{
return;
}
/*-- free the next node --*/
if (pdez_node->next != NULL)
{
dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
}
/*-- free the node content --*/
content = (DEZ_NODE_CLASS *)(pdez_node->content);
if (content != NULL)
{
if (content->branch_node) dez_node_specs[content->branch_node->dez_op].dez_node_free_func(content->branch_node);
free(content);
}
/*-- free the node self */
free(pdez_node);
}
static void dez_node_free_da (DEZ_NODE *pdez_node)
{
DEZ_NODE_DA *content;
if (pdez_node == NULL)
{
return;
}
/*-- free the next node --*/
if (pdez_node->next != NULL)
{
dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
}
/*-- free the node content --*/
content = (DEZ_NODE_DA *)(pdez_node->content);
if (content != NULL)
{
if (content->branch_node) dez_node_specs[content->branch_node->dez_op].dez_node_free_func(content->branch_node);
if (content->key_node) dez_node_specs[content->key_node->dez_op].dez_node_free_func(content->key_node);
if (content->value_node) dez_node_specs[content->value_node->dez_op].dez_node_free_func(content->value_node);
if (content->next_node) dez_node_specs[content->next_node->dez_op].dez_node_free_func(content->next_node);
free(content);
}
/*-- free the node self */
free(pdez_node);
}
static void dez_node_free_array (DEZ_NODE *pdez_node)
{
if (pdez_node == NULL)
{
return;
}
/*-- free the next node --*/
if (pdez_node->next != NULL)
{
dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
}
/*-- free the node content --*/
if (pdez_node->content != NULL)
{
/**********/
free(pdez_node->content);
}
/*-- free the node self */
free(pdez_node);
}
static void dez_node_free_list (DEZ_NODE *pdez_node)
{
DEZ_NODE_LIST *content;
if (pdez_node == NULL)
{
return;
}
/*-- free the next node --*/
if (pdez_node->next != NULL)
{
dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
}
/*-- free the node content --*/
content = (DEZ_NODE_LIST *)(pdez_node->content);
if (content != NULL)
{
if (content->branch_node) dez_node_specs[content->branch_node->dez_op].dez_node_free_func(content->branch_node);
if (content->le_node) dez_node_specs[content->le_node->dez_op].dez_node_free_func(content->le_node);
if (content->dest_node) dez_node_specs[content->dest_node->dez_op].dez_node_free_func(content->dest_node);
free(content);
}
/*-- free the node self */
free(pdez_node);
}
static void dez_node_free_le (DEZ_NODE *pdez_node)
{
DEZ_NODE_LE *content;
if (pdez_node == NULL)
{
return;
}
/*-- free the next node --*/
if (pdez_node->next != NULL)
{
dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
}
/*-- free the node content --*/
content = (DEZ_NODE_LE *)(pdez_node->content);
if (content != NULL)
{
if (content->branch_node) dez_node_specs[content->branch_node->dez_op].dez_node_free_func(content->branch_node);
if (content->a_node) dez_node_specs[content->a_node->dez_op].dez_node_free_func(content->a_node);
free(content);
}
/*-- free the node self */
free(pdez_node);
}
static void dez_node_free_heredoc (DEZ_NODE *pdez_node)
{
if (pdez_node == NULL)
{
return;
}
/*-- free the next node --*/
if (pdez_node->next != NULL)
{
dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
}
/*-- free the node content --*/
if (pdez_node->content != NULL)
{
/**********/
free(pdez_node->content);
}
/*-- free the node self */
free(pdez_node);
}
static void dez_node_free_dollar_open_curly_braces (DEZ_NODE *pdez_node)
{
if (pdez_node == NULL)
{
return;
}
/*-- free the next node --*/
if (pdez_node->next != NULL)
{
dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
}
/*-- free the node content --*/
if (pdez_node->content != NULL)
{
/**********/
free(pdez_node->content);
}
/*-- free the node self */
free(pdez_node);
}
static void dez_node_free_unknown (DEZ_NODE *pdez_node)
{
if (pdez_node == NULL)
{
return;
}
/*-- free the next node --*/
if (pdez_node->next != NULL)
{
dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
}
/*-- free the node content --*/
if (pdez_node->content != NULL)
{
/**********/
free(pdez_node->content);
}
/*-- free the node self */
free(pdez_node);
}
/**********************************************************
* dez_dump_op: dump a dez op
*
* @param dez_op: the dez op code need to be dumped
* @return 0: normal, 1: enter a branch, 2: exit the branch, 3: need to continue -1: error
**********************************************************/
static int dez_dump_op (unsigned char dez_op)
{
return dez_node_specs[dez_op].dez_node_cvt_func (dez_op, m_op_buffer[0]);
}
/**********************************************************
* dez_dump_zend_op: dump a zend op
*
* @param pzop: pointer to the zend_op need to be dumped
* @return 0: normal, 1: enter a branch, 2: exit the branch, -1: error
**********************************************************/
static int dez_dump_zend_op (zend_op *pzop)
{
//printf ( "%u,", pzop->opcode);
//return 0;
printf ( " %6u:", ZEND_LINENUM(pzop));
if (pzop->opcode >= sizeof(ZEND_OP_STRING)/sizeof(ZEND_OP_STRING[0]))
{
printf ( "<%u> ", pzop->opcode);
}
else
{
printf ("%s", ZEND_OP_STRING[pzop->opcode]);
}
dez_dump_znode_ex(&(pzop->result), 1);
printf ( ", ");
dez_dump_znode_ex(&(pzop->op1), 1);
printf ( ", ");
dez_dump_znode_ex(&(pzop->op2), 1);
printf ( "\r\n");
return 0;
// return dez_node_specs[DEZ_OP_UNKNOWN].dez_node_cvt_func (DEZ_OP_UNKNOWN, pzop);
}
/**********************************************************
* dez_deal_op: deal with a zend_op
*
* @param pzop: pointer to the zend_op would be dealed with. NULL means uninitialization
* @param match_n: used to retreive the number of matching zend_op
* @return 0: success, 1: enter a branch, 2: exit the branch, -1: error
**********************************************************/
static int dez_deal_op (zend_op *pzop, short *match_n)
{
static unsigned char *op_masks = NULL; /* each element: 0: need to continue, 1: not matching, 2: matching */
static int op_num = 0;
register int i;
int needcontinues;
short mn;
int matching_i;
int r;
*match_n = 0;
if (op_masks == NULL) /* initialization */
{
op_masks = (unsigned char *)malloc(sizeof(dez_op_types)/sizeof(dez_op_types[0]));
if (op_masks == NULL) /* fail to alloc memery */
{
return -1;
}
op_num = sizeof(dez_op_types)/sizeof(dez_op_types[0]);
memset (op_masks, 0, op_num); /* initialize op_masks */
}
if (pzop != NULL)
{
if (dez_opc_push (pzop) != 0) /* push the zend op into stack */
{ /* fail */
return -1;
}
}
needcontinues = 0;
mn = 0;
for (i = 0; i < op_num; i++)
{
if (op_masks[i] == 0) /* need to continue */
{
op_masks[i] = dez_opc_compare (dez_op_types[i].opcs, dez_op_types[i].opcs_len);
}
switch (op_masks[i])
{
case 0: /* need to continue */
needcontinues++;
break;
case 1: /* not matching */
break;
case 2: /* matching */
if (mn < dez_op_types[i].opcs_len)
{
mn = dez_op_types[i].opcs_len;
matching_i = i;
}
break;
}
}
if (pzop == NULL) /* uninitialization */
{
if (m_opc_num > 0) /* the stack is not empty */
{
if (mn > 0) /* any dez op is matching */
{
*match_n = mn;
dez_dump_op (dez_op_types[matching_i].dez_op); /* dump the matching dez op */
}
else /* all dez ops ara not matching */
{
mn = 1;
*match_n = mn;
dez_dump_zend_op (m_op_buffer[0]); /* dump the zend op at the top of stack */
}
memset (op_masks, 0, op_num); /* reset op_masks */
dez_opc_pop(mn);
dez_deal_op (NULL, match_n);
}
else
{
if (op_masks != NULL)
{
free (op_masks);
op_masks = NULL;
}
}
}
else if (needcontinues == 0) /* no one dez op need to continue */
{
if (mn > 0) /* any dez op is matching */
{
*match_n = mn;
do
{
r = dez_dump_op (dez_op_types[matching_i].dez_op); /* dump the matching dez op */
} while(r == 3); /* continue to deal with the zend op */
}
else /* all dez ops ara not matching */
{
mn = 1;
*match_n = mn;
r = dez_dump_zend_op (m_op_buffer[0]); /* dump the zend op at the top of stack */
}
memset (op_masks, 0, op_num); /* reset op_masks */
return r;
}
return 0;
}
/**********************************************************
* dez_deal_op_end: end process
*
* @param header: the header of dez nodes
* @param perant: the parent node
* @return 0: success; other: failed
**********************************************************/
static int dez_deal_node_end(DEZ_NODE *header, DEZ_NODE *parent)
{
DEZ_NODE_EXPR *content;
DEZ_NODE *p, *next;
int begin, end, prevcond;
DEZ_BRK_CNT_NODE *pbcn_header, *pbcn, *pbcn_next;
pbcn_header = m_dez_brk_cnt_tail;
begin = 0;
end = 100000;
prevcond = -1;
dez_branch_get_range(parent, &begin, &end);
if (parent != NULL && parent->dez_op == DEZ_OP_DO)
{
DEZ_NODE *prev, *sub;
prev = dez_get_last_sub_node(parent);
while(prev)
{
if (
prev->dez_op == DEZ_OP_DO || /* do{...}while() */
prev->dez_op == DEZ_OP_WHILE && prev->zop->opcode == ZEND_JMP /* while(true) */
)
{
break;
}
sub = dez_get_last_sub_node(prev);
if (sub == NULL)
{
break;
}
prev = sub;
}
if (prev == NULL) /* no sub branch */
{
prevcond = get_prev_zend_linenum(parent);
}
else
{
prevcond = get_zend_linenum(prev);
}
}
else if (parent != NULL && parent->dez_op == DEZ_OP_FOR)
{
DEZ_NODE *before_node = ((DEZ_NODE_FOR *)(parent->content))->before_node;
if (before_node != NULL)
{
prevcond = get_zend_linenum(before_node);
}
else
{
prevcond = get_prev_zend_linenum(parent);
}
}
else
{
prevcond = get_prev_zend_linenum(parent);
}
p = header;
while(p != NULL)
{
content = (DEZ_NODE_EXPR *)(p->content);
if (p->dez_op == DEZ_OP_IF && p->zop->opcode == ZEND_JMP) /* if (false) node */
{
int dest;
if (content != NULL && content->branch_node != NULL) /* sub branch is exist */
{
dez_node_specs[content->branch_node->dez_op].dez_node_free_func(content->branch_node); /* remove the sub branch */
content->branch_node = NULL;
}
dest = p->zop->op1.u.opline_num;
if (dest < begin || dest > end) /* jmp out of the branch */
{
if (p->next != NULL)
{
dez_node_specs[p->next->dez_op].dez_node_free_func(p->next); /* remove remainder nodes in this branch */
p->next = NULL;
}
}
((DEZ_NODE_IF *)content)->dest = 0; /* maybe break */
dez_brk_cnt_add(p);
}
else if (content != NULL && content->branch_node != NULL) /* sub branch is exist */
{
dez_node_push(p); /* for get_prev_zend_linenum() */
dez_deal_node_end(content->branch_node, p); /* deal with the sub branch */
dez_node_pop(); /* for get_prev_zend_linenum() */
}
p = p->next;
}
if (pbcn_header != NULL)
{
pbcn = pbcn_header->next;
}
else
{
pbcn = m_dez_brk_cnt_root;
}
while(pbcn != NULL)
{
DEZ_NODE *n;
DEZ_NODE_IF *c;
int dest;
int checked;
pbcn_next = pbcn->next;
n = (DEZ_NODE*)(pbcn->node);
c = (DEZ_NODE_IF *)(n->content);
dest = n->zop->op1.u.opline_num;
checked = 0;
if (
parent != NULL &&
(
parent->dez_op == DEZ_OP_WHILE ||
parent->dez_op == DEZ_OP_DO ||
parent->dez_op == DEZ_OP_FOR ||
parent->dez_op == DEZ_OP_FOREACH ||
parent->dez_op == DEZ_OP_SWITCH
)
) /* loop or switch */
{
int endcond;
if (parent->dez_op == DEZ_OP_WHILE && parent->zop->opcode == ZEND_JMP) /* while(true) */
{
endcond = prevcond+1;
}
else
{
endcond = get_zend_linenum(parent);
}
if (dest < begin || dest > end) /* jmp out of the branch */
{
n->dez_op = DEZ_OP_BREAK;
c->dest++;
checked = 1;
}
else if (
c->dest == 0 && /* maybe continue */
dest > prevcond && dest <= endcond /* jmp to condition */
)
{
n->dez_op = DEZ_OP_CONTINUE;
checked = 1;
}
}
else if (
parent != NULL &&
parent->dez_op == DEZ_OP_IF
)
{
if (
n->dez_op == DEZ_OP_BREAK &&
dest > prevcond && /* jmp to condition */
dest <= get_zend_linenum(parent) /* */
)
{
parent->dez_op = DEZ_OP_WHILE; /* IF -> WHILE */
}
}
if (checked != 0) /* break or continue was found */
{
#if 0
if (c != NULL && c->branch_node != NULL) /* sub branch is exist */
{
DEZ_NODE *lastsubnode = c->branch_node;
while(lastsubnode->next != NULL)
{
lastsubnode = lastsubnode->next;
}
lastsubnode->next = n->next;
if (lastsubnode->next != NULL) lastsubnode->next->prev = lastsubnode;
n->next = c->branch_node->next;
if (n->next != NULL) n->next->prev = n;
c->branch_node->next = NULL;
free(c->branch_node);
c->branch_node = NULL;
}
#endif
}
if (dest >= begin && dest <= end) /* jmp within the branch */
{
dez_brk_cnt_del(pbcn);
if (n->dez_op == DEZ_OP_IF) /* not break/continue */
{
DEZ_DEL_NODE(n);
}
else if(n->dez_op == DEZ_OP_CONTINUE) /* the continue node */
{
DEZ_NODE *lastsubnode = dez_get_last_sub_node(parent);
if (lastsubnode == n) /* the continue node is last node in branch */
{
DEZ_DEL_NODE(n);
}
}
}
pbcn = pbcn_next;
}
return 0;
}
/**********************************************************
* dez_decompile: decompile some zend ops
*
* @param ops: the array of zend_ops would be decompiled
* @param n: the number of ops
* @return 0: success; other: failed
**********************************************************/
static int dez_decompile (zend_op *ops, int n)
{
int r;
DEZ_NODE_EXPR *content;
static struct _zend_executor_globals *zeg;
TSRMLS_FETCH();
dez_prep_zend_op(ops, n); /* pre process the zend op */
m_zend_op_start = ops;
m_zend_op_end = ops+n;
m_zend_op_current = m_zend_op_start;
while (m_zend_op_current < m_zend_op_end)
{
zeg = (struct _zend_executor_globals *)&EG(return_value_ptr_ptr);
//dez_dump_zend_op(m_zend_op_current); /****** for debug */
//m_zend_op_current++;
//continue;
r = dez_deal_op (m_zend_op_current, &m_zend_op_match_n); /* deal with a zend_op */
if (r == 0) /* success to deal with the zend_op */
{
/* do nothing */
}
else if (r == 1) /* enter a branch */
{
dez_enter_branch();
}
else if (r == 2) /* exit the branch */
{
dez_exit_branch(1); /* exit the branch */
}
else /* error */
{
return r;
}
dez_check_exit_branch();
dez_opc_pop (m_zend_op_match_n); /* pop the matching zend op */
if (m_opc_num > 0) /* some zend_ops is in stack */
{
dez_opc_refresh(); /* update the opcodes in stack */
}
m_zend_op_current++;
}
dez_deal_op(NULL, &m_zend_op_match_n); /* process the remainder zend op in stack */
dez_check_exit_all(); /* exit all branch */
dez_deal_node_end(m_dez_op_root, NULL); /* end process (make BREAK, CONTINUE node) */
dez_brk_cnt_free(); /* free the break/continue list */
clear_or_recover_zend_op(NULL, 0, 0); /* clear the opcodes cleared */
return 0;
}
/**********************************************************
* dez_output: output the zend nodes
*
* @param header: the header of dez nodes
* @param perant: the parent node
* @return 0: success; other: failed
**********************************************************/
static int dez_output (DEZ_NODE *header, DEZ_NODE *parent)
{
static char m_tab[1024] = {' ',' ','\0'};
static int m_dez_declare = 0;
static int m_dez_silence = 0;
DEZ_NODE_EXPR *content;
DEZ_NODE *p, *next;
DEZ_NODE *function_node;
if (m_dez_declare > 0)
{
m_dez_declare++;
}
p = header;
while(p != NULL)
{
next = p->next;
if (
p->dez_op == DEZ_OP_NOP ||
p->dez_op == DEZ_OP_DECLARE
)
{
p = next;
continue;
}
else if (p->dez_op == DEZ_OP_BEGIN_SILENCE)
{
m_dez_silence = 1;
p = next;
continue;
}
else if (p->dez_op == DEZ_OP_END_SILENCE)
{
m_dez_silence = 0;
p = next;
continue;
}
if (
next != NULL &&
next->dez_op == DEZ_OP_DECLARE
)
{
if (m_dez_declare == 0)
{
m_dez_declare = 1; /* enter declare branch */
printf ("%s", m_tab);
dez_node_specs[next->dez_op].dez_node_output_func (next);
printf ("\r\n%s{\r\n", m_tab);
strcat(m_tab, " ");
}
}
else
{
if (m_dez_declare == 1)
{
m_dez_declare = 0; /* exit declare branch */
m_tab[strlen(m_tab)-2] = '\0';
printf ("%s}\r\n\r\n", m_tab);
}
}
/*-- remove the last return in function() or main branch --*/
if (
next == NULL &&
(parent == NULL || parent->dez_op == DEZ_OP_FUNCTION) &&
p->dez_op == DEZ_OP_RETURN
) /* the last return */
{
break; /* skip the last return */
}
if (p->dez_op == DEZ_OP_FUNCTION)
{
function_node = m_current_function; /* save the old function node */
m_current_function = p;
}
printf ("%s", m_tab);
if (m_dez_silence != 0) /* silence */
{
printf ("%s", dez_node_specs[DEZ_OP_BEGIN_SILENCE].desc);
}
dez_node_specs[p->dez_op].dez_node_output_func (p);
content = (DEZ_NODE_EXPR *)(p->content);
if (content != NULL && content->branch_node != NULL) /* enter branch */
{
printf ("\r\n%s{\r\n", m_tab);
strcat(m_tab, " ");
dez_output (content->branch_node, p); /* output the branch */
m_tab[strlen(m_tab)-2] = '\0';
if (p->dez_op == DEZ_OP_DO)
{
printf ( "%s}", m_tab);
p->dez_op = DEZ_OP_WHILE;
dez_node_output_if(p); /* output while(...) */
p->dez_op = DEZ_OP_DO;
printf ( ";\r\n");
}
else
{
printf ( "%s}\r\n", m_tab);
}
if (p->next != NULL && p->next->dez_op != DEZ_OP_ELSE)
{
printf ( "\r\n");
}
}
else
{
printf ( ";\r\n");
}
if (p->dez_op == DEZ_OP_FUNCTION)
{
m_current_function = function_node; /* restore the old function node */
}
p = next;
}
if (m_dez_declare > 0)
{
m_dez_declare--;
if (m_dez_declare == 0) /* exit declare branch */
{
m_tab[strlen(m_tab)-2] = '\0';
printf ( "%s}\r\n\r\n", m_tab);
}
}
return 0;
}
/**********************************************************
* dez_property: decompile properties
*
* @param ht: properties
* @return 0: success; other: failed
**********************************************************/
static int dez_property (HashTable *ht)
{
DEZ_NODE *parent;
DEZ_NODE_CLASS *ccontent;
if (ht != NULL)
{
Bucket *p = ht->pListHead;
parent = dez_node_get();
/*-- decompile properties --*/
while(p != NULL)
{
DEZ_NODE *node;
DEZ_NODE_VAR *content;
if (
parent != NULL &&
parent->dez_op == DEZ_OP_CLASS
) /* property declaration */
{
ccontent = (DEZ_NODE_CLASS *)(parent->content);
if (ccontent->parent != NULL) /* extands */
{
HashTable *pht = &(ccontent->parent->default_properties);
Bucket *pp = pht->pListHead;
while(pp != NULL)
{
if (
strcmp((char *)(pp->arKey), (char *)(p->arKey)) == 0 &&
*((zval **)(pp->pData)) == *((zval **)(p->pData))
) /* property for parent class */
{
break;
}
pp = pp->pListNext;
}
if (pp != NULL) /* the method belongs parent class */
{
p = p->pListNext;
continue;
}
}
}
content = (DEZ_NODE_VAR *)malloc(sizeof(DEZ_NODE_VAR));
if (content == NULL)
{
return -1;
}
node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
if (node == NULL)
{
free(content);
return -1;
}
content->branch_node = NULL;
content->property = p;
node->dez_op = DEZ_OP_VAR;
node->zop = NULL;
node->content = content;
DEZ_ADD_NODE(node);
p = p->pListNext;
}
}
return 0;
}
/**********************************************************
* dez_function: decompile functions
*
* @param ht: function_table
* @return 0: success; other: failed
**********************************************************/
static int dez_function (HashTable *ht)
{
static zend_op_array *op_array;
DEZ_NODE *parent;
DEZ_NODE_CLASS *ccontent;
if (ht != NULL)
{
Bucket *p = ht->pListHead;
parent = dez_node_get();
/*-- decompile the user functions --*/
while(p != NULL)
{
op_array = (zend_op_array *)(p->pData);
if (
op_array != NULL &&
op_array->type == 2 /* user function */
)
{
DEZ_NODE *node;
DEZ_NODE_FUNCTION *content;
if (
parent != NULL &&
parent->dez_op == DEZ_OP_CLASS
) /* method declaration */
{
ccontent = (DEZ_NODE_CLASS *)(parent->content);
if (ccontent->parent != NULL) /* extands */
{
HashTable *pht = &(ccontent->parent->function_table);
Bucket *pp = pht->pListHead;
while(pp != NULL)
{
if (((zend_op_array *)(pp->pData))->opcodes == op_array->opcodes) /* function for parent class */
{
break;
}
pp = pp->pListNext;
}
if (pp != NULL) /* the method belongs parent class */
{
p = p->pListNext;
continue;
}
}
}
content = (DEZ_NODE_FUNCTION *)malloc(sizeof(DEZ_NODE_FUNCTION));
if (content == NULL)
{
return -1;
}
node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
if (node == NULL)
{
free(content);
return -1;
}
content->branch_node = NULL;
content->param_node = NULL;
content->name = op_array->function_name;
content->m_dez_var_num = 0;
content->op_array = op_array;
node->dez_op = DEZ_OP_FUNCTION;
node->zop = op_array->opcodes;
node->content = content;
DEZ_ADD_NODE(node);
//printf("*%s:\r\n", op_array->function_name);
m_current_function = node;
dez_enter_branch(); /* enter function branch */
dez_decompile (op_array->opcodes, op_array->size); /* zend op -> dez op */
dez_exit_branch(0); /* exit function branch */
m_current_function = NULL;
}
p = p->pListNext;
}
}
return 0;
}
/**********************************************************
* dez_class: decompile classes
*
* @param none
* @return 0: success; other: failed
**********************************************************/
static int dez_class (void)
{
static HashTable *ht;
static zend_class_entry *c_entry;
static zend_op_array *op_array;
TSRMLS_FETCH();
ht = (EG(class_table));
if (ht != NULL)
{
Bucket *p = ht->pListHead;
/*-- decompile the user functions --*/
while(p != NULL)
{
c_entry = (zend_class_entry *)(p->pData);
if (
c_entry != NULL &&
c_entry->type == ZEND_USER_CLASS /* user class */
)
{
DEZ_NODE *node;
DEZ_NODE_CLASS *content;
content = (DEZ_NODE_CLASS *)malloc(sizeof(DEZ_NODE_CLASS));
if (content == NULL)
{
return -1;
}
node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
if (node == NULL)
{
free(content);
return -1;
}
content->branch_node = NULL;
content->name = c_entry->name;
content->parent = c_entry->parent;
node->dez_op = DEZ_OP_CLASS;
node->zop = NULL;
node->content = content;
DEZ_ADD_NODE(node);
//printf("class %s:\r\n", c_entry->name);
dez_enter_branch(); /* enter class branch */
dez_property (&(c_entry->default_properties)); /* decompile the properties */
dez_function (&(c_entry->function_table)); /* decompile the motheds */
dez_exit_branch(0); /* exit class branch */
}
p = p->pListNext;
}
}
return 0;
}
/**********************************************************
* dez_global: decompile global source
*
* @param none
* @return 0: success; other: failed
**********************************************************/
static int dez_global (void)
{
TSRMLS_FETCH();
m_current_function = NULL;
return dez_decompile (EG(active_op_array)->opcodes, EG(active_op_array)->size); /* zend op -> dez op */
}
/**********************************************************
* dez_main: decompile the zend op
*
* @param none
* @return 0: success; other: failed
**********************************************************/
int dez_main (void)
{
TSRMLS_FETCH();
static char *m_Header =
"/***********************************************************************/\r\n"
"/* */\r\n"
"/* This file is created by Dezender */\r\n"
"/* */\r\n"
"/* Dezender (Decoder for Zend Encoder/SafeGuard): */\r\n"
"/* Version: 0.9.0.1 */\r\n"
"/* Author: qinvent.com */\r\n"
"/* Release Date: 2005.10.04 */\r\n"
"/* */\r\n"
"/***********************************************************************/\r\n"
"\r\n\r\n";
m_dez_op_root = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
if (m_dez_op_root == NULL) /* fail to alloc memory */
{
return -1;
}
m_dez_op_root->dez_op = DEZ_OP_NOP;
m_dez_op_root->zop = NULL;
m_dez_op_root->content = NULL;
m_dez_op_root->prev = NULL;
m_dez_op_root->next = NULL;
m_dez_op_current = m_dez_op_root;
dez_class (); /* decompile classes */
dez_function (EG(function_table)); /* decompile functions */
dez_global (); /* decompile global source */
m_current_function = NULL;
printf ( "<?php\r\n%s", m_Header);
dez_output(m_dez_op_root, NULL); /* output the dez nodes */
printf ( "?>\r\n");
dez_node_free(); /* free dez nodes */
return 0;
}
/************************************************
* @ dezender.c v1.0 log @
*
* Revision 1.0.0.0 lkq 2005/08/10
* create the file
*
***********************************************/