|
|
|
@ -566,6 +566,7 @@ class Decompiler |
|
|
|
|
XC_ASSIGN => "=", |
|
|
|
|
XC_ASSIGN_REF => "= &", |
|
|
|
|
XC_JMP_SET => "?:", |
|
|
|
|
XC_JMP_SET_VAR => "?:", |
|
|
|
|
XC_JMPZ_EX => "&&", |
|
|
|
|
XC_JMPNZ_EX => "||", |
|
|
|
|
); |
|
|
|
@ -595,6 +596,7 @@ class Decompiler |
|
|
|
|
// }}} |
|
|
|
|
function stripNamespace($name) // {{{ |
|
|
|
|
{ |
|
|
|
|
$name = str($name); |
|
|
|
|
$len = strlen($this->namespace) + 1; |
|
|
|
|
if (substr($name, 0, $len) == $this->namespace . '\\') { |
|
|
|
|
return substr($name, $len); |
|
|
|
@ -663,6 +665,9 @@ class Decompiler |
|
|
|
|
case XC_IS_VAR: |
|
|
|
|
case XC_IS_TMP_VAR: |
|
|
|
|
$T = &$EX['Ts']; |
|
|
|
|
if (!isset($T[$op['var']])) { |
|
|
|
|
printBacktrace(); |
|
|
|
|
} |
|
|
|
|
$ret = $T[$op['var']]; |
|
|
|
|
if ($free && empty($this->keepTs)) { |
|
|
|
|
unset($T[$op['var']]); |
|
|
|
@ -833,12 +838,12 @@ class Decompiler |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
// }}} |
|
|
|
|
// {{{ ?: excluding JMP_SET |
|
|
|
|
// {{{ ?: excluding JMP_SET/JMP_SET_VAR |
|
|
|
|
if ($firstOp['opcode'] == XC_JMPZ && !empty($firstOp['jmpouts']) |
|
|
|
|
&& $range[1] >= $range[0] + 3 |
|
|
|
|
&& $opcodes[$firstOp['jmpouts'][0] - 2]['opcode'] == XC_QM_ASSIGN |
|
|
|
|
&& ($opcodes[$firstOp['jmpouts'][0] - 2]['opcode'] == XC_QM_ASSIGN || $opcodes[$firstOp['jmpouts'][0] - 2]['opcode'] == XC_QM_ASSIGN_VAR) |
|
|
|
|
&& $opcodes[$firstOp['jmpouts'][0] - 1]['opcode'] == XC_JMP && $opcodes[$firstOp['jmpouts'][0] - 1]['jmpouts'][0] == $range[1] + 1 |
|
|
|
|
&& $lastOp['opcode'] == XC_QM_ASSIGN |
|
|
|
|
&& ($lastOp['opcode'] == XC_QM_ASSIGN || $lastOp['opcode'] == XC_QM_ASSIGN_VAR) |
|
|
|
|
) { |
|
|
|
|
$trueRange = array($range[0] + 1, $firstOp['jmpouts'][0] - 2); |
|
|
|
|
$falseRange = array($firstOp['jmpouts'][0], $range[1]); |
|
|
|
@ -1013,9 +1018,9 @@ class Decompiler |
|
|
|
|
$this->dasmBasicBlock($EX, array($catchFirst, $catchOpLine)); |
|
|
|
|
$catchOp = &$opcodes[$catchOpLine]; |
|
|
|
|
echo $indent, 'catch (' |
|
|
|
|
, isset($catchOp['op1']['constant']) ? $catchOp['op1']['constant'] : str($this->getOpVal($catchOp['op1'], $EX)) |
|
|
|
|
, $this->stripNamespace(isset($catchOp['op1']['constant']) ? $catchOp['op1']['constant'] : str($this->getOpVal($catchOp['op1'], $EX))) |
|
|
|
|
, ' ' |
|
|
|
|
, str($this->getOpVal($catchOp['op2'], $EX)) |
|
|
|
|
, isset($catchOp['op2']['constant']) ? '$' . $catchOp['op2']['constant'] : str($this->getOpVal($catchOp['op2'], $EX)) |
|
|
|
|
, ") {", PHP_EOL; |
|
|
|
|
unset($catchOp); |
|
|
|
|
|
|
|
|
@ -1314,6 +1319,7 @@ class Decompiler |
|
|
|
|
case XC_JMPZ_EX: |
|
|
|
|
case XC_JMPNZ_EX: |
|
|
|
|
// case XC_JMP_SET: |
|
|
|
|
// case XC_JMP_SET_VAR: |
|
|
|
|
// case XC_FE_RESET: |
|
|
|
|
case XC_FE_FETCH: |
|
|
|
|
// case XC_JMP_NO_CTOR: |
|
|
|
@ -1474,7 +1480,7 @@ class Decompiler |
|
|
|
|
array_push($EX['arg_types_stack'], array($EX['fbc'], $EX['object'], $EX['called_scope'])); |
|
|
|
|
$EX['object'] = (int) $res['var']; |
|
|
|
|
$EX['called_scope'] = null; |
|
|
|
|
$EX['fbc'] = 'new ' . unquoteName($this->getOpVal($op1, $EX), $EX); |
|
|
|
|
$EX['fbc'] = 'new ' . $this->stripNamespace($this->getOpVal($op1, $EX)); |
|
|
|
|
break; |
|
|
|
|
// }}} |
|
|
|
|
case XC_THROW: // {{{ |
|
|
|
@ -1489,7 +1495,7 @@ class Decompiler |
|
|
|
|
break; |
|
|
|
|
// }}} |
|
|
|
|
case XC_INSTANCEOF: // {{{ |
|
|
|
|
$resvar = str($this->getOpVal($op1, $EX)) . ' instanceof ' . str($this->getOpVal($op2, $EX)); |
|
|
|
|
$resvar = str($this->getOpVal($op1, $EX)) . ' instanceof ' . $this->stripNamespace($this->getOpVal($op2, $EX)); |
|
|
|
|
break; |
|
|
|
|
// }}} |
|
|
|
|
case XC_FETCH_CLASS: // {{{ |
|
|
|
@ -1536,27 +1542,37 @@ class Decompiler |
|
|
|
|
case XC_FETCH_FUNC_ARG: |
|
|
|
|
case XC_FETCH_UNSET: |
|
|
|
|
case XC_FETCH_IS: |
|
|
|
|
case XC_UNSET_VAR: |
|
|
|
|
$rvalue = $this->getOpVal($op1, $EX); |
|
|
|
|
$fetchtype = defined('ZEND_FETCH_TYPE_MASK') ? ($ext & ZEND_FETCH_TYPE_MASK) : $op2['EA.type']; |
|
|
|
|
if ($fetchtype == ZEND_FETCH_STATIC_MEMBER) { |
|
|
|
|
$rvalue = $this->stripNamespace($op2['constant']) . '::$' . unquoteName($rvalue, $EX); |
|
|
|
|
} |
|
|
|
|
else if ($opc != XC_UNSET_VAR) { |
|
|
|
|
$name = unquoteName($rvalue, $EX); |
|
|
|
|
$fetchType = defined('ZEND_FETCH_TYPE_MASK') ? ($ext & ZEND_FETCH_TYPE_MASK) : $op2['EA.type']; |
|
|
|
|
$name = isset($op1['constant']) ? $op1['constant'] : unquoteName($this->getOpVal($op1, $EX), $EX); |
|
|
|
|
if ($fetchType == ZEND_FETCH_STATIC_MEMBER) { |
|
|
|
|
$class = isset($op2['constant']) ? $op2['constant'] : $this->getOpVal($op2, $EX); |
|
|
|
|
$rvalue = $this->stripNamespace($class) . '::$' . $name; |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
$rvalue = $this->getOpVal($op1, $EX); |
|
|
|
|
$globalname = xcache_is_autoglobal($name) ? "\$$name" : "\$GLOBALS[" . str($rvalue) . "]"; |
|
|
|
|
$rvalue = new Decompiler_Fetch($rvalue, $fetchtype, $globalname); |
|
|
|
|
$rvalue = new Decompiler_Fetch($rvalue, $fetchType, $globalname); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ($opc == XC_UNSET_VAR) { |
|
|
|
|
$op['php'] = "unset(" . str($rvalue, $EX) . ")"; |
|
|
|
|
$lastphpop = &$op; |
|
|
|
|
} |
|
|
|
|
else if ($res['op_type'] != XC_IS_UNUSED) { |
|
|
|
|
if ($res['op_type'] != XC_IS_UNUSED) { |
|
|
|
|
$resvar = $rvalue; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
// }}} |
|
|
|
|
case XC_UNSET_VAR: // {{{ |
|
|
|
|
$fetchType = defined('ZEND_FETCH_TYPE_MASK') ? ($ext & ZEND_FETCH_TYPE_MASK) : $op2['EA.type']; |
|
|
|
|
if ($fetchType == ZEND_FETCH_STATIC_MEMBER) { |
|
|
|
|
$class = isset($op2['constant']) ? $op2['constant'] /* PHP5.3- */ : $this->getOpVal($op2, $EX); |
|
|
|
|
$rvalue = $this->stripNamespace($class) . '::$' . $op1['constant']; |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
$rvalue = $this->getOpVal($op1, $EX); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
$op['php'] = "unset(" . str($rvalue, $EX) . ")"; |
|
|
|
|
$lastphpop = &$op; |
|
|
|
|
break; |
|
|
|
|
// }}} |
|
|
|
|
// {{{ case FETCH_DIM_* |
|
|
|
|
case XC_FETCH_DIM_TMP_VAR: |
|
|
|
|
case XC_FETCH_DIM_R: |
|
|
|
@ -1737,7 +1753,8 @@ class Decompiler |
|
|
|
|
} |
|
|
|
|
$fetchtype = defined('ZEND_FETCH_TYPE_MASK') ? ($ext & ZEND_FETCH_TYPE_MASK) : $op2['EA.type']; |
|
|
|
|
if ($fetchtype == ZEND_FETCH_STATIC_MEMBER) { |
|
|
|
|
$rvalue = $this->stripNamespace($op2['constant']) . '::' . unquoteName($rvalue, $EX); |
|
|
|
|
$class = isset($op2['constant']) ? $op2['constant'] : $this->getOpVal($op2, $EX); |
|
|
|
|
$rvalue = $this->stripNamespace($class) . '::' . unquoteName($rvalue, $EX); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else if ($opc == XC_ISSET_ISEMPTY) { |
|
|
|
@ -2049,9 +2066,6 @@ class Decompiler |
|
|
|
|
// }}} |
|
|
|
|
case XC_JMP_NO_CTOR: |
|
|
|
|
break; |
|
|
|
|
case XC_JMP_SET: // ?: |
|
|
|
|
$resvar = new Decompiler_Binop($this, $this->getOpVal($op1, $EX), XC_JMP_SET, null); |
|
|
|
|
break; |
|
|
|
|
case XC_JMPZ_EX: // and |
|
|
|
|
case XC_JMPNZ_EX: // or |
|
|
|
|
$resvar = $this->getOpVal($op1, $EX); |
|
|
|
@ -2468,7 +2482,7 @@ class Decompiler |
|
|
|
|
} |
|
|
|
|
echo $isInterface ? 'interface ' : 'class ', $this->stripNamespace($class['name']); |
|
|
|
|
if ($class['parent']) { |
|
|
|
|
echo ' extends ', $class['parent']; |
|
|
|
|
echo ' extends ', $this->stripNamespace($class['parent']); |
|
|
|
|
} |
|
|
|
|
/* TODO */ |
|
|
|
|
if (!empty($class['interfaces'])) { |
|
|
|
@ -2856,6 +2870,7 @@ foreach (array ( |
|
|
|
|
'XC_ISSET_ISEMPTY' => -1, |
|
|
|
|
'XC_JMP_NO_CTOR' => -1, |
|
|
|
|
'XC_JMP_SET' => -1, |
|
|
|
|
'XC_JMP_SET_VAR' => -1, |
|
|
|
|
'XC_QM_ASSIGN_VAR' => -1, |
|
|
|
|
'XC_UNSET_DIM_OBJ' => -1, |
|
|
|
|
) as $k => $v) { |
|
|
|
|