Changeset 802 for trunk/Decompiler.class.php
- Timestamp:
- 2011-04-27T06:42:25+02:00 (2 years ago)
- File:
-
- 1 edited
-
trunk/Decompiler.class.php (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Decompiler.class.php
r801 r802 181 181 } 182 182 183 return str($op1, $indent) . ' ' . $opstr . ' '. str($op2, $indent);183 return str($op1, $indent) . ' ' . $opstr . ($this->opc == XC_ASSIGN_REF ? '' : ' ') . str($op2, $indent); 184 184 } 185 185 } … … 518 518 XC_ASSIGN_BW_XOR => "^=", 519 519 XC_BOOL_XOR => "xor", 520 XC_ASSIGN => "=", 521 XC_ASSIGN_REF => "= &", 520 522 XC_JMP_SET => "?:", 523 XC_JMPZ_EX => "&&", 524 XC_JMPNZ_EX => "||", 521 525 ); 522 526 // }}} … … 740 744 $lastOp = &$opcodes[$range[1]]; 741 745 746 // {{{ && || and or 747 if (($firstOp['opcode'] == XC_JMPZ_EX || $firstOp['opcode'] == XC_JMPNZ_EX) && !empty($firstOp['jmpouts']) 748 && $firstOp['jmpouts'][0] == $range[1] + 1 749 && $lastOp['opcode'] == XC_BOOL 750 && $firstOp['opcode']['result']['var'] == $lastOp['opcode']['result']['var'] 751 ) { 752 $this->removeJmpInfo($EX, $range[0]); 753 754 $this->recognizeAndDecompileClosedBlocks($EX, array($range[0], $range[0]), $indent . INDENT); 755 $op1 = $this->getOpVal($firstOp['op1'], $EX, false, true); 756 757 $this->recognizeAndDecompileClosedBlocks($EX, array($range[0] + 1, $range[1]), $indent . INDENT); 758 $op2 = $this->getOpVal($lastOp['op1'], $EX, false, true); 759 760 $T[$firstOp['result']['var']] = new Decompiler_Binop($this, $op1, $firstOp['opcode'], $op2); 761 return false; 762 } 763 // }}} 742 764 // {{{ ?: excluding JMP_SET 743 765 if ($firstOp['opcode'] == XC_JMPZ && !empty($firstOp['jmpouts']) … … 1343 1365 // echo $opname, "\n"; 1344 1366 1345 $call = array(&$this, $opname); 1346 if (is_callable($call)) { 1347 $this->usedOps[$opc] = true; 1348 $this->{$opname}($op, $EX); 1349 } 1350 else if (isset($this->binops[$opc])) { // {{{ 1351 $this->usedOps[$opc] = true; 1352 $op1val = $this->getOpVal($op1, $EX, false); 1353 $op2val = $this->getOpVal($op2, $EX, false); 1354 $rvalue = new Decompiler_Binop($this, $op1val, $opc, $op2val); 1355 $resvar = $rvalue; 1356 // }}} 1357 } 1358 else if (isset($this->unaryops[$opc])) { // {{{ 1359 $this->usedOps[$opc] = true; 1360 $op1val = $this->getOpVal($op1, $EX); 1361 $myop = $this->unaryops[$opc]; 1362 $rvalue = $myop . str($op1val); 1363 $resvar = $rvalue; 1364 // }}} 1365 } 1366 else { 1367 $covered = true; 1368 switch ($opc) { 1369 case XC_NEW: // {{{ 1370 array_push($EX['arg_types_stack'], array($EX['fbc'], $EX['object'], $EX['called_scope'])); 1371 $EX['object'] = (int) $res['var']; 1372 $EX['called_scope'] = null; 1373 $EX['fbc'] = 'new ' . unquoteName($this->getOpVal($op1, $EX), $EX); 1374 if (!ZEND_ENGINE_2) { 1375 $resvar = '$new object$'; 1376 } 1367 $notHandled = false; 1368 switch ($opc) { 1369 case XC_NEW: // {{{ 1370 array_push($EX['arg_types_stack'], array($EX['fbc'], $EX['object'], $EX['called_scope'])); 1371 $EX['object'] = (int) $res['var']; 1372 $EX['called_scope'] = null; 1373 $EX['fbc'] = 'new ' . unquoteName($this->getOpVal($op1, $EX), $EX); 1374 if (!ZEND_ENGINE_2) { 1375 $resvar = '$new object$'; 1376 } 1377 break; 1378 // }}} 1379 case XC_THROW: // {{{ 1380 $resvar = 'throw ' . str($this->getOpVal($op1, $EX)); 1381 break; 1382 // }}} 1383 case XC_CLONE: // {{{ 1384 $resvar = 'clone ' . str($this->getOpVal($op1, $EX)); 1385 break; 1386 // }}} 1387 case XC_CATCH: // {{{ 1388 break; 1389 // }}} 1390 case XC_INSTANCEOF: // {{{ 1391 $resvar = str($this->getOpVal($op1, $EX)) . ' instanceof ' . str($this->getOpVal($op2, $EX)); 1392 break; 1393 // }}} 1394 case XC_FETCH_CLASS: // {{{ 1395 if ($op2['op_type'] == XC_IS_UNUSED) { 1396 switch (($ext & (defined('ZEND_FETCH_CLASS_MASK') ? ZEND_FETCH_CLASS_MASK : 0xFF))) { 1397 case ZEND_FETCH_CLASS_SELF: 1398 $class = 'self'; 1399 break; 1400 case ZEND_FETCH_CLASS_PARENT: 1401 $class = 'parent'; 1402 break; 1403 case ZEND_FETCH_CLASS_STATIC: 1404 $class = 'static'; 1405 break; 1406 } 1407 $istmpres = true; 1408 } 1409 else { 1410 $class = $this->getOpVal($op2, $EX); 1411 if (isset($op2['constant'])) { 1412 $class = $this->stripNamespace(unquoteName($class)); 1413 } 1414 } 1415 $resvar = $class; 1416 break; 1417 // }}} 1418 case XC_FETCH_CONSTANT: // {{{ 1419 if ($op1['op_type'] == XC_IS_UNUSED) { 1420 $resvar = $this->stripNamespace($op2['constant']); 1377 1421 break; 1378 // }}} 1379 case XC_THROW: // {{{ 1380 $resvar = 'throw ' . str($this->getOpVal($op1, $EX)); 1422 } 1423 1424 if ($op1['op_type'] == XC_IS_CONST) { 1425 $resvar = $this->stripNamespace($op1['constant']); 1426 } 1427 else { 1428 $resvar = $this->getOpVal($op1, $EX); 1429 } 1430 1431 $resvar = str($resvar) . '::' . unquoteName($this->getOpVal($op2, $EX)); 1432 break; 1433 // }}} 1434 // {{{ case XC_FETCH_* 1435 case XC_FETCH_R: 1436 case XC_FETCH_W: 1437 case XC_FETCH_RW: 1438 case XC_FETCH_FUNC_ARG: 1439 case XC_FETCH_UNSET: 1440 case XC_FETCH_IS: 1441 case XC_UNSET_VAR: 1442 $rvalue = $this->getOpVal($op1, $EX); 1443 if (defined('ZEND_FETCH_TYPE_MASK')) { 1444 $fetchtype = ($ext & ZEND_FETCH_TYPE_MASK); 1445 } 1446 else { 1447 $fetchtype = $op2[!ZEND_ENGINE_2 ? 'fetch_type' : 'EA.type']; 1448 } 1449 switch ($fetchtype) { 1450 case ZEND_FETCH_STATIC_MEMBER: 1451 $class = $this->getOpVal($op2, $EX); 1452 $rvalue = str($class) . '::$' . unquoteName($rvalue, $EX); 1381 1453 break; 1382 // }}} 1383 case XC_CLONE: // {{{ 1384 $resvar = 'clone ' . str($this->getOpVal($op1, $EX)); 1454 default: 1455 $name = unquoteName($rvalue, $EX); 1456 $globalname = xcache_is_autoglobal($name) ? "\$$name" : "\$GLOBALS[" . str($rvalue) . "]"; 1457 $rvalue = new Decompiler_Fetch($rvalue, $fetchtype, $globalname); 1385 1458 break; 1386 // }}} 1387 case XC_CATCH: // {{{ 1459 } 1460 if ($opc == XC_UNSET_VAR) { 1461 $op['php'] = "unset(" . str($rvalue, $EX) . ")"; 1462 $lastphpop = &$op; 1463 } 1464 else if ($res['op_type'] != XC_IS_UNUSED) { 1465 $resvar = $rvalue; 1466 } 1467 break; 1468 // }}} 1469 // {{{ case XC_FETCH_DIM_* 1470 case XC_FETCH_DIM_TMP_VAR: 1471 case XC_FETCH_DIM_R: 1472 case XC_FETCH_DIM_W: 1473 case XC_FETCH_DIM_RW: 1474 case XC_FETCH_DIM_FUNC_ARG: 1475 case XC_FETCH_DIM_UNSET: 1476 case XC_FETCH_DIM_IS: 1477 case XC_ASSIGN_DIM: 1478 case XC_UNSET_DIM_OBJ: // PHP 4 only 1479 case XC_UNSET_DIM: 1480 case XC_UNSET_OBJ: 1481 $src = $this->getOpVal($op1, $EX, false); 1482 if (is_a($src, "Decompiler_ForeachBox")) { 1483 $src->iskey = $this->getOpVal($op2, $EX); 1484 $resvar = $src; 1388 1485 break; 1389 // }}} 1390 case XC_INSTANCEOF: // {{{ 1391 $resvar = str($this->getOpVal($op1, $EX)) . ' instanceof ' . str($this->getOpVal($op2, $EX)); 1486 } 1487 1488 if (is_a($src, "Decompiler_DimBox")) { 1489 $dimbox = $src; 1490 } 1491 else { 1492 if (!is_a($src, "Decompiler_ListBox")) { 1493 $op1val = $this->getOpVal($op1, $EX, false); 1494 $list = new Decompiler_List(isset($op1val) ? $op1val : '$this'); 1495 1496 $src = new Decompiler_ListBox($list); 1497 if (!isset($op1['var'])) { 1498 $this->dumpop($op, $EX); 1499 var_dump($op); 1500 die('missing var'); 1501 } 1502 $T[$op1['var']] = $src; 1503 unset($list); 1504 } 1505 $dim = new Decompiler_Dim($src); 1506 $src->obj->dims[] = &$dim; 1507 1508 $dimbox = new Decompiler_DimBox($dim); 1509 } 1510 $dim = &$dimbox->obj; 1511 $dim->offsets[] = $this->getOpVal($op2, $EX); 1512 if ($ext == ZEND_FETCH_ADD_LOCK) { 1513 $src->obj->everLocked = true; 1514 } 1515 else if ($ext == ZEND_FETCH_STANDARD) { 1516 $dim->isLast = true; 1517 } 1518 if ($opc == XC_UNSET_OBJ) { 1519 $dim->isObject = true; 1520 } 1521 unset($dim); 1522 $rvalue = $dimbox; 1523 unset($dimbox); 1524 1525 if ($opc == XC_ASSIGN_DIM) { 1526 $lvalue = $rvalue; 1527 ++ $i; 1528 $rvalue = $this->getOpVal($opcodes[$i]['op1'], $EX); 1529 $resvar = str($lvalue, $EX) . ' = ' . str($rvalue); 1530 } 1531 else if ($opc == XC_UNSET_DIM || $opc == XC_UNSET_OBJ) { 1532 $op['php'] = "unset(" . str($rvalue, $EX) . ")"; 1533 $lastphpop = &$op; 1534 } 1535 else if ($res['op_type'] != XC_IS_UNUSED) { 1536 $resvar = $rvalue; 1537 } 1538 break; 1539 // }}} 1540 case XC_ASSIGN: // {{{ 1541 $lvalue = $this->getOpVal($op1, $EX); 1542 $rvalue = $this->getOpVal($op2, $EX, false); 1543 if (is_a($rvalue, 'Decompiler_ForeachBox')) { 1544 $type = $rvalue->iskey ? 'fe_key' : 'fe_as'; 1545 $rvalue->obj[$type] = $lvalue; 1546 unset($T[$op2['var']]); 1392 1547 break; 1393 // }}} 1394 case XC_FETCH_CLASS: // {{{ 1395 if ($op2['op_type'] == XC_IS_UNUSED) { 1396 switch (($ext & (defined('ZEND_FETCH_CLASS_MASK') ? ZEND_FETCH_CLASS_MASK : 0xFF))) { 1397 case ZEND_FETCH_CLASS_SELF: 1398 $class = 'self'; 1399 break; 1400 case ZEND_FETCH_CLASS_PARENT: 1401 $class = 'parent'; 1402 break; 1403 case ZEND_FETCH_CLASS_STATIC: 1404 $class = 'static'; 1405 break; 1406 } 1407 $istmpres = true; 1408 } 1409 else { 1410 $class = $this->getOpVal($op2, $EX); 1411 if (isset($op2['constant'])) { 1412 $class = $this->stripNamespace(unquoteName($class)); 1413 } 1414 } 1415 $resvar = $class; 1548 } 1549 if (is_a($rvalue, "Decompiler_DimBox")) { 1550 $dim = &$rvalue->obj; 1551 $dim->assign = $lvalue; 1552 if ($dim->isLast) { 1553 $resvar = foldToCode($dim->value, $EX); 1554 } 1555 unset($dim); 1416 1556 break; 1417 // }}} 1418 case XC_FETCH_CONSTANT: // {{{ 1419 if ($op1['op_type'] == XC_IS_UNUSED) { 1420 $resvar = $this->stripNamespace($op2['constant']); 1421 break; 1422 } 1423 1424 if ($op1['op_type'] == XC_IS_CONST) { 1425 $resvar = $this->stripNamespace($op1['constant']); 1426 } 1427 else { 1428 $resvar = $this->getOpVal($op1, $EX); 1429 } 1430 1431 $resvar = str($resvar) . '::' . unquoteName($this->getOpVal($op2, $EX)); 1432 break; 1433 // }}} 1434 // {{{ case XC_FETCH_* 1435 case XC_FETCH_R: 1436 case XC_FETCH_W: 1437 case XC_FETCH_RW: 1438 case XC_FETCH_FUNC_ARG: 1439 case XC_FETCH_UNSET: 1440 case XC_FETCH_IS: 1441 case XC_UNSET_VAR: 1442 $rvalue = $this->getOpVal($op1, $EX); 1443 if (defined('ZEND_FETCH_TYPE_MASK')) { 1444 $fetchtype = ($ext & ZEND_FETCH_TYPE_MASK); 1445 } 1446 else { 1447 $fetchtype = $op2[!ZEND_ENGINE_2 ? 'fetch_type' : 'EA.type']; 1448 } 1449 switch ($fetchtype) { 1450 case ZEND_FETCH_STATIC_MEMBER: 1451 $class = $this->getOpVal($op2, $EX); 1452 $rvalue = str($class) . '::$' . unquoteName($rvalue, $EX); 1453 break; 1454 default: 1455 $name = unquoteName($rvalue, $EX); 1456 $globalname = xcache_is_autoglobal($name) ? "\$$name" : "\$GLOBALS[" . str($rvalue) . "]"; 1457 $rvalue = new Decompiler_Fetch($rvalue, $fetchtype, $globalname); 1458 break; 1459 } 1460 if ($opc == XC_UNSET_VAR) { 1461 $op['php'] = "unset(" . str($rvalue, $EX) . ")"; 1462 $lastphpop = &$op; 1463 } 1464 else if ($res['op_type'] != XC_IS_UNUSED) { 1465 $resvar = $rvalue; 1466 } 1467 break; 1468 // }}} 1469 // {{{ case XC_FETCH_DIM_* 1470 case XC_FETCH_DIM_TMP_VAR: 1471 case XC_FETCH_DIM_R: 1472 case XC_FETCH_DIM_W: 1473 case XC_FETCH_DIM_RW: 1474 case XC_FETCH_DIM_FUNC_ARG: 1475 case XC_FETCH_DIM_UNSET: 1476 case XC_FETCH_DIM_IS: 1477 case XC_ASSIGN_DIM: 1478 case XC_UNSET_DIM_OBJ: // PHP 4 only 1479 case XC_UNSET_DIM: 1480 case XC_UNSET_OBJ: 1481 $src = $this->getOpVal($op1, $EX, false); 1482 if (is_a($src, "Decompiler_ForeachBox")) { 1483 $src->iskey = $this->getOpVal($op2, $EX); 1484 $resvar = $src; 1485 break; 1486 } 1487 1488 if (is_a($src, "Decompiler_DimBox")) { 1489 $dimbox = $src; 1490 } 1491 else { 1492 if (!is_a($src, "Decompiler_ListBox")) { 1493 $op1val = $this->getOpVal($op1, $EX, false); 1494 $list = new Decompiler_List(isset($op1val) ? $op1val : '$this'); 1495 1496 $src = new Decompiler_ListBox($list); 1497 if (!isset($op1['var'])) { 1498 $this->dumpop($op, $EX); 1499 var_dump($op); 1500 die('missing var'); 1501 } 1502 $T[$op1['var']] = $src; 1503 unset($list); 1504 } 1505 $dim = new Decompiler_Dim($src); 1506 $src->obj->dims[] = &$dim; 1507 1508 $dimbox = new Decompiler_DimBox($dim); 1509 } 1510 $dim = &$dimbox->obj; 1511 $dim->offsets[] = $this->getOpVal($op2, $EX); 1512 if ($ext == ZEND_FETCH_ADD_LOCK) { 1513 $src->obj->everLocked = true; 1514 } 1515 else if ($ext == ZEND_FETCH_STANDARD) { 1516 $dim->isLast = true; 1517 } 1518 if ($opc == XC_UNSET_OBJ) { 1519 $dim->isObject = true; 1520 } 1521 unset($dim); 1522 $rvalue = $dimbox; 1523 unset($dimbox); 1524 1525 if ($opc == XC_ASSIGN_DIM) { 1526 $lvalue = $rvalue; 1527 ++ $i; 1528 $rvalue = $this->getOpVal($opcodes[$i]['op1'], $EX); 1529 $resvar = str($lvalue, $EX) . ' = ' . str($rvalue); 1530 } 1531 else if ($opc == XC_UNSET_DIM || $opc == XC_UNSET_OBJ) { 1532 $op['php'] = "unset(" . str($rvalue, $EX) . ")"; 1533 $lastphpop = &$op; 1534 } 1535 else if ($res['op_type'] != XC_IS_UNUSED) { 1536 $resvar = $rvalue; 1537 } 1538 break; 1539 // }}} 1540 case XC_ASSIGN: // {{{ 1541 $lvalue = $this->getOpVal($op1, $EX); 1542 $rvalue = $this->getOpVal($op2, $EX, false); 1543 if (is_a($rvalue, 'Decompiler_ForeachBox')) { 1544 $type = $rvalue->iskey ? 'fe_key' : 'fe_as'; 1545 $rvalue->obj[$type] = $lvalue; 1546 unset($T[$op2['var']]); 1547 break; 1548 } 1549 if (is_a($rvalue, "Decompiler_DimBox")) { 1550 $dim = &$rvalue->obj; 1551 $dim->assign = $lvalue; 1552 if ($dim->isLast) { 1553 $resvar = foldToCode($dim->value, $EX); 1554 } 1555 unset($dim); 1556 break; 1557 } 1558 if (is_a($rvalue, 'Decompiler_Fetch')) { 1559 $src = str($rvalue->src, $EX); 1560 if ('$' . unquoteName($src) == $lvalue) { 1561 switch ($rvalue->fetchType) { 1562 case ZEND_FETCH_STATIC: 1563 $statics = &$EX['op_array']['static_variables']; 1564 if ((xcache_get_type($statics[$name]) & IS_LEXICAL_VAR)) { 1565 $EX['uses'][] = str($lvalue); 1566 unset($statics); 1567 break 2; 1568 } 1569 unset($statics); 1570 } 1571 } 1572 } 1573 $resvar = "$lvalue = " . str($rvalue, $EX); 1574 break; 1575 // }}} 1576 case XC_ASSIGN_REF: // {{{ 1577 $lvalue = $this->getOpVal($op1, $EX); 1578 $rvalue = $this->getOpVal($op2, $EX, false); 1579 if (is_a($rvalue, 'Decompiler_Fetch')) { 1580 $src = str($rvalue->src, $EX); 1581 if ('$' . unquoteName($src) == $lvalue) { 1582 switch ($rvalue->fetchType) { 1583 case ZEND_FETCH_GLOBAL: 1584 case ZEND_FETCH_GLOBAL_LOCK: 1585 $resvar = 'global ' . $lvalue; 1586 break 2; 1587 case ZEND_FETCH_STATIC: 1588 $statics = &$EX['op_array']['static_variables']; 1589 if ((xcache_get_type($statics[$name]) & IS_LEXICAL_REF)) { 1590 $EX['uses'][] = '&' . str($lvalue); 1591 unset($statics); 1592 break 2; 1593 } 1594 1595 $resvar = 'static ' . $lvalue; 1596 $name = unquoteName($src); 1597 if (isset($statics[$name])) { 1598 $var = $statics[$name]; 1599 $resvar .= ' = '; 1600 $resvar .= str(value($var), $EX); 1601 } 1557 } 1558 if (is_a($rvalue, 'Decompiler_Fetch')) { 1559 $src = str($rvalue->src, $EX); 1560 if ('$' . unquoteName($src) == $lvalue) { 1561 switch ($rvalue->fetchType) { 1562 case ZEND_FETCH_STATIC: 1563 $statics = &$EX['op_array']['static_variables']; 1564 if ((xcache_get_type($statics[$name]) & IS_LEXICAL_VAR)) { 1565 $EX['uses'][] = str($lvalue); 1602 1566 unset($statics); 1603 1567 break 2; 1604 default:1605 1568 } 1569 unset($statics); 1606 1570 } 1607 1571 } 1608 // TODO: PHP_6 global 1609 $rvalue = str($rvalue, $EX); 1610 $resvar = "$lvalue = &$rvalue"; 1572 } 1573 $resvar = new Decompiler_Binop($this, $lvalue, XC_ASSIGN, $rvalue); 1574 break; 1575 // }}} 1576 case XC_ASSIGN_REF: // {{{ 1577 $lvalue = $this->getOpVal($op1, $EX); 1578 $rvalue = $this->getOpVal($op2, $EX, false); 1579 if (is_a($rvalue, 'Decompiler_Fetch')) { 1580 $src = str($rvalue->src, $EX); 1581 if ('$' . unquoteName($src) == $lvalue) { 1582 switch ($rvalue->fetchType) { 1583 case ZEND_FETCH_GLOBAL: 1584 case ZEND_FETCH_GLOBAL_LOCK: 1585 $resvar = 'global ' . $lvalue; 1586 break 2; 1587 case ZEND_FETCH_STATIC: 1588 $statics = &$EX['op_array']['static_variables']; 1589 if ((xcache_get_type($statics[$name]) & IS_LEXICAL_REF)) { 1590 $EX['uses'][] = '&' . str($lvalue); 1591 unset($statics); 1592 break 2; 1593 } 1594 1595 $resvar = 'static ' . $lvalue; 1596 $name = unquoteName($src); 1597 if (isset($statics[$name])) { 1598 $var = $statics[$name]; 1599 $resvar .= ' = '; 1600 $resvar .= str(value($var), $EX); 1601 } 1602 unset($statics); 1603 break 2; 1604 default: 1605 } 1606 } 1607 } 1608 // TODO: PHP_6 global 1609 $resvar = new Decompiler_Binop($this, $lvalue, XC_ASSIGN_REF, $rvalue); 1610 break; 1611 // }}} 1612 // {{{ case XC_FETCH_OBJ_* 1613 case XC_FETCH_OBJ_R: 1614 case XC_FETCH_OBJ_W: 1615 case XC_FETCH_OBJ_RW: 1616 case XC_FETCH_OBJ_FUNC_ARG: 1617 case XC_FETCH_OBJ_UNSET: 1618 case XC_FETCH_OBJ_IS: 1619 case XC_ASSIGN_OBJ: 1620 $obj = $this->getOpVal($op1, $EX); 1621 if (!isset($obj)) { 1622 $obj = '$this'; 1623 } 1624 $rvalue = str($obj) . "->" . unquoteVariableName($this->getOpVal($op2, $EX), $EX); 1625 if ($res['op_type'] != XC_IS_UNUSED) { 1626 $resvar = $rvalue; 1627 } 1628 if ($opc == XC_ASSIGN_OBJ) { 1629 ++ $i; 1630 $lvalue = $rvalue; 1631 $rvalue = $this->getOpVal($opcodes[$i]['op1'], $EX); 1632 $resvar = "$lvalue = " . str($rvalue); 1633 } 1634 break; 1635 // }}} 1636 case XC_ISSET_ISEMPTY_DIM_OBJ: 1637 case XC_ISSET_ISEMPTY_PROP_OBJ: 1638 case XC_ISSET_ISEMPTY: 1639 case XC_ISSET_ISEMPTY_VAR: // {{{ 1640 if ($opc == XC_ISSET_ISEMPTY_VAR) { 1641 $rvalue = $this->getOpVal($op1, $EX); 1642 // for < PHP_5_3 1643 if ($op1['op_type'] == XC_IS_CONST) { 1644 $rvalue = '$' . unquoteVariableName($this->getOpVal($op1, $EX)); 1645 } 1646 if ($op2['EA.type'] == ZEND_FETCH_STATIC_MEMBER) { 1647 $class = $this->getOpVal($op2, $EX); 1648 $rvalue = $class . '::' . $rvalue; 1649 } 1650 } 1651 else if ($opc == XC_ISSET_ISEMPTY) { 1652 $rvalue = $this->getOpVal($op1, $EX); 1653 } 1654 else { 1655 $container = $this->getOpVal($op1, $EX); 1656 $dim = $this->getOpVal($op2, $EX); 1657 if ($opc == XC_ISSET_ISEMPTY_PROP_OBJ) { 1658 if (!isset($container)) { 1659 $container = '$this'; 1660 } 1661 $rvalue = $container . "->" . unquoteVariableName($dim); 1662 } 1663 else { 1664 $rvalue = $container . '[' . str($dim) .']'; 1665 } 1666 } 1667 1668 switch ((!ZEND_ENGINE_2 ? $op['op2']['var'] /* constant */ : $ext) & (ZEND_ISSET|ZEND_ISEMPTY)) { 1669 case ZEND_ISSET: 1670 $rvalue = "isset(" . str($rvalue) . ")"; 1611 1671 break; 1612 // }}} 1613 // {{{ case XC_FETCH_OBJ_* 1614 case XC_FETCH_OBJ_R: 1615 case XC_FETCH_OBJ_W: 1616 case XC_FETCH_OBJ_RW: 1617 case XC_FETCH_OBJ_FUNC_ARG: 1618 case XC_FETCH_OBJ_UNSET: 1619 case XC_FETCH_OBJ_IS: 1620 case XC_ASSIGN_OBJ: 1672 case ZEND_ISEMPTY: 1673 $rvalue = "empty(" . str($rvalue) . ")"; 1674 break; 1675 } 1676 $resvar = $rvalue; 1677 break; 1678 // }}} 1679 case XC_SEND_VAR_NO_REF: 1680 case XC_SEND_VAL: 1681 case XC_SEND_REF: 1682 case XC_SEND_VAR: // {{{ 1683 $ref = ($opc == XC_SEND_REF ? '&' : ''); 1684 $EX['argstack'][] = $ref . str($this->getOpVal($op1, $EX)); 1685 break; 1686 // }}} 1687 case XC_INIT_STATIC_METHOD_CALL: 1688 case XC_INIT_METHOD_CALL: // {{{ 1689 array_push($EX['arg_types_stack'], array($EX['fbc'], $EX['object'], $EX['called_scope'])); 1690 if ($opc == XC_INIT_STATIC_METHOD_CALL || $opc == XC_INIT_METHOD_CALL || $op1['op_type'] != XC_IS_UNUSED) { 1621 1691 $obj = $this->getOpVal($op1, $EX); 1622 1692 if (!isset($obj)) { 1623 1693 $obj = '$this'; 1624 1694 } 1625 $rvalue = str($obj) . "->" . unquoteVariableName($this->getOpVal($op2, $EX), $EX); 1695 if ($opc == XC_INIT_STATIC_METHOD_CALL || /* PHP4 */ isset($op1['constant'])) { 1696 $EX['object'] = null; 1697 $EX['called_scope'] = $this->stripNamespace(unquoteName($obj, $EX)); 1698 } 1699 else { 1700 $EX['object'] = $obj; 1701 $EX['called_scope'] = null; 1702 } 1626 1703 if ($res['op_type'] != XC_IS_UNUSED) { 1627 $resvar = $rvalue; 1628 } 1629 if ($opc == XC_ASSIGN_OBJ) { 1630 ++ $i; 1631 $lvalue = $rvalue; 1632 $rvalue = $this->getOpVal($opcodes[$i]['op1'], $EX); 1633 $resvar = "$lvalue = " . str($rvalue); 1634 } 1635 break; 1636 // }}} 1637 case XC_ISSET_ISEMPTY_DIM_OBJ: 1638 case XC_ISSET_ISEMPTY_PROP_OBJ: 1639 case XC_ISSET_ISEMPTY: 1640 case XC_ISSET_ISEMPTY_VAR: // {{{ 1641 if ($opc == XC_ISSET_ISEMPTY_VAR) { 1642 $rvalue = $this->getOpVal($op1, $EX); 1643 // for < PHP_5_3 1644 if ($op1['op_type'] == XC_IS_CONST) { 1645 $rvalue = '$' . unquoteVariableName($this->getOpVal($op1, $EX)); 1646 } 1647 if ($op2['EA.type'] == ZEND_FETCH_STATIC_MEMBER) { 1648 $class = $this->getOpVal($op2, $EX); 1649 $rvalue = $class . '::' . $rvalue; 1650 } 1651 } 1652 else if ($opc == XC_ISSET_ISEMPTY) { 1653 $rvalue = $this->getOpVal($op1, $EX); 1654 } 1655 else { 1656 $container = $this->getOpVal($op1, $EX); 1657 $dim = $this->getOpVal($op2, $EX); 1658 if ($opc == XC_ISSET_ISEMPTY_PROP_OBJ) { 1659 if (!isset($container)) { 1660 $container = '$this'; 1661 } 1662 $rvalue = $container . "->" . unquoteVariableName($dim); 1663 } 1664 else { 1665 $rvalue = $container . '[' . str($dim) .']'; 1666 } 1667 } 1668 1669 switch ((!ZEND_ENGINE_2 ? $op['op2']['var'] /* constant */ : $ext) & (ZEND_ISSET|ZEND_ISEMPTY)) { 1670 case ZEND_ISSET: 1671 $rvalue = "isset(" . str($rvalue) . ")"; 1672 break; 1673 case ZEND_ISEMPTY: 1674 $rvalue = "empty(" . str($rvalue) . ")"; 1675 break; 1676 } 1677 $resvar = $rvalue; 1678 break; 1679 // }}} 1680 case XC_SEND_VAR_NO_REF: 1681 case XC_SEND_VAL: 1682 case XC_SEND_REF: 1683 case XC_SEND_VAR: // {{{ 1684 $ref = ($opc == XC_SEND_REF ? '&' : ''); 1685 $EX['argstack'][] = $ref . str($this->getOpVal($op1, $EX)); 1686 break; 1687 // }}} 1688 case XC_INIT_STATIC_METHOD_CALL: 1689 case XC_INIT_METHOD_CALL: // {{{ 1690 array_push($EX['arg_types_stack'], array($EX['fbc'], $EX['object'], $EX['called_scope'])); 1691 if ($opc == XC_INIT_STATIC_METHOD_CALL || $opc == XC_INIT_METHOD_CALL || $op1['op_type'] != XC_IS_UNUSED) { 1692 $obj = $this->getOpVal($op1, $EX); 1693 if (!isset($obj)) { 1694 $obj = '$this'; 1695 } 1696 if ($opc == XC_INIT_STATIC_METHOD_CALL || /* PHP4 */ isset($op1['constant'])) { 1697 $EX['object'] = null; 1698 $EX['called_scope'] = $this->stripNamespace(unquoteName($obj, $EX)); 1699 } 1700 else { 1701 $EX['object'] = $obj; 1702 $EX['called_scope'] = null; 1703 } 1704 if ($res['op_type'] != XC_IS_UNUSED) { 1705 $resvar = '$obj call$'; 1706 } 1707 } 1708 else { 1709 $EX['object'] = null; 1710 $EX['called_scope'] = null; 1711 } 1712 1713 $EX['fbc'] = $this->getOpVal($op2, $EX, false); 1714 if (($opc == XC_INIT_STATIC_METHOD_CALL || $opc == XC_INIT_METHOD_CALL) && !isset($EX['fbc'])) { 1715 $EX['fbc'] = '__construct'; 1716 } 1717 break; 1718 // }}} 1719 case XC_INIT_NS_FCALL_BY_NAME: 1720 case XC_INIT_FCALL_BY_NAME: // {{{ 1721 array_push($EX['arg_types_stack'], array($EX['fbc'], $EX['object'], $EX['called_scope'])); 1722 if (!ZEND_ENGINE_2 && ($ext & ZEND_CTOR_CALL)) { 1723 break; 1724 } 1704 $resvar = '$obj call$'; 1705 } 1706 } 1707 else { 1725 1708 $EX['object'] = null; 1726 1709 $EX['called_scope'] = null; 1727 $EX['fbc'] = $this->getOpVal($op2, $EX); 1710 } 1711 1712 $EX['fbc'] = $this->getOpVal($op2, $EX, false); 1713 if (($opc == XC_INIT_STATIC_METHOD_CALL || $opc == XC_INIT_METHOD_CALL) && !isset($EX['fbc'])) { 1714 $EX['fbc'] = '__construct'; 1715 } 1716 break; 1717 // }}} 1718 case XC_INIT_NS_FCALL_BY_NAME: 1719 case XC_INIT_FCALL_BY_NAME: // {{{ 1720 array_push($EX['arg_types_stack'], array($EX['fbc'], $EX['object'], $EX['called_scope'])); 1721 if (!ZEND_ENGINE_2 && ($ext & ZEND_CTOR_CALL)) { 1728 1722 break; 1729 // }}} 1730 case XC_INIT_FCALL_BY_FUNC: // {{{ deprecated even in PHP 4? 1731 $EX['object'] = null; 1732 $EX['called_scope'] = null; 1733 $which = $op1['var']; 1734 $EX['fbc'] = $EX['op_array']['funcs'][$which]['name']; 1723 } 1724 $EX['object'] = null; 1725 $EX['called_scope'] = null; 1726 $EX['fbc'] = $this->getOpVal($op2, $EX); 1727 break; 1728 // }}} 1729 case XC_INIT_FCALL_BY_FUNC: // {{{ deprecated even in PHP 4? 1730 $EX['object'] = null; 1731 $EX['called_scope'] = null; 1732 $which = $op1['var']; 1733 $EX['fbc'] = $EX['op_array']['funcs'][$which]['name']; 1734 break; 1735 // }}} 1736 case XC_DO_FCALL_BY_FUNC: 1737 $which = $op1['var']; 1738 $fname = $EX['op_array']['funcs'][$which]['name']; 1739 $args = $this->popargs($EX, $ext); 1740 $resvar = $fname . "($args)"; 1741 break; 1742 case XC_DO_FCALL: 1743 $fname = unquoteName($this->getOpVal($op1, $EX, false), $EX); 1744 $args = $this->popargs($EX, $ext); 1745 $resvar = $fname . "($args)"; 1746 break; 1747 case XC_DO_FCALL_BY_NAME: // {{{ 1748 $object = null; 1749 1750 $fname = unquoteName($EX['fbc'], $EX); 1751 if (!is_int($EX['object'])) { 1752 $object = $EX['object']; 1753 } 1754 1755 $args = $this->popargs($EX, $ext); 1756 1757 $prefix = (isset($object) ? $object . '->' : '' ) 1758 . (isset($EX['called_scope']) ? $EX['called_scope'] . '::' : '' ); 1759 $resvar = $prefix 1760 . (!$prefix ? $this->stripNamespace($fname) : $fname) 1761 . "($args)"; 1762 unset($args); 1763 1764 if (is_int($EX['object'])) { 1765 $T[$EX['object']] = $resvar; 1766 $resvar = null; 1767 } 1768 list($EX['fbc'], $EX['object'], $EX['called_scope']) = array_pop($EX['arg_types_stack']); 1769 break; 1770 // }}} 1771 case XC_VERIFY_ABSTRACT_CLASS: // {{{ 1772 //unset($T[$op1['var']]); 1773 break; 1774 // }}} 1775 case XC_DECLARE_CLASS: 1776 case XC_DECLARE_INHERITED_CLASS: 1777 case XC_DECLARE_INHERITED_CLASS_DELAYED: // {{{ 1778 $key = $op1['constant']; 1779 if (!isset($this->dc['class_table'][$key])) { 1780 echo 'class not found: ', $key, 'existing classes are:', "\n"; 1781 var_dump(array_keys($this->dc['class_table'])); 1782 exit; 1783 } 1784 $class = &$this->dc['class_table'][$key]; 1785 if (!isset($class['name'])) { 1786 $class['name'] = unquoteName($this->getOpVal($op2, $EX), $EX); 1787 } 1788 if ($opc == XC_DECLARE_INHERITED_CLASS || $opc == XC_DECLARE_INHERITED_CLASS_DELAYED) { 1789 $ext /= XC_SIZEOF_TEMP_VARIABLE; 1790 $class['parent'] = $T[$ext]; 1791 unset($T[$ext]); 1792 } 1793 else { 1794 $class['parent'] = null; 1795 } 1796 1797 for (;;) { 1798 if ($i + 1 <= $range[1] 1799 && $opcodes[$i + 1]['opcode'] == XC_ADD_INTERFACE 1800 && $opcodes[$i + 1]['op1']['var'] == $res['var']) { 1801 // continue 1802 } 1803 else if ($i + 2 <= $range[1] 1804 && $opcodes[$i + 2]['opcode'] == XC_ADD_INTERFACE 1805 && $opcodes[$i + 2]['op1']['var'] == $res['var'] 1806 && $opcodes[$i + 1]['opcode'] == XC_FETCH_CLASS) { 1807 // continue 1808 } 1809 else { 1810 break; 1811 } 1812 $this->usedOps[XC_ADD_INTERFACE] = true; 1813 1814 $fetchop = &$opcodes[$i + 1]; 1815 $interface = $this->stripNamespace(unquoteName($this->getOpVal($fetchop['op2'], $EX), $EX)); 1816 $addop = &$opcodes[$i + 2]; 1817 $class['interfaces'][$addop['extended_value']] = $interface; 1818 unset($fetchop, $addop); 1819 $i += 2; 1820 } 1821 $this->dclass($class); 1822 echo "\n"; 1823 unset($class); 1824 break; 1825 // }}} 1826 case XC_INIT_STRING: // {{{ 1827 $resvar = "''"; 1828 break; 1829 // }}} 1830 case XC_ADD_CHAR: 1831 case XC_ADD_STRING: 1832 case XC_ADD_VAR: // {{{ 1833 $op1val = $this->getOpVal($op1, $EX); 1834 $op2val = $this->getOpVal($op2, $EX); 1835 switch ($opc) { 1836 case XC_ADD_CHAR: 1837 $op2val = value(chr(str($op2val))); 1735 1838 break; 1736 // }}} 1737 case XC_DO_FCALL_BY_FUNC: 1738 $which = $op1['var']; 1739 $fname = $EX['op_array']['funcs'][$which]['name']; 1740 $args = $this->popargs($EX, $ext); 1741 $resvar = $fname . "($args)"; 1839 case XC_ADD_STRING: 1742 1840 break; 1743 case XC_DO_FCALL: 1744 $fname = unquoteName($this->getOpVal($op1, $EX, false), $EX); 1745 $args = $this->popargs($EX, $ext); 1746 $resvar = $fname . "($args)"; 1841 case XC_ADD_VAR: 1747 1842 break; 1748 case XC_DO_FCALL_BY_NAME: // {{{ 1749 $object = null; 1750 1751 $fname = unquoteName($EX['fbc'], $EX); 1752 if (!is_int($EX['object'])) { 1753 $object = $EX['object']; 1754 } 1755 1756 $args = $this->popargs($EX, $ext); 1757 1758 $prefix = (isset($object) ? $object . '->' : '' ) 1759 . (isset($EX['called_scope']) ? $EX['called_scope'] . '::' : '' ); 1760 $resvar = $prefix 1761 . (!$prefix ? $this->stripNamespace($fname) : $fname) 1762 . "($args)"; 1763 unset($args); 1764 1765 if (is_int($EX['object'])) { 1766 $T[$EX['object']] = $resvar; 1767 $resvar = null; 1768 } 1769 list($EX['fbc'], $EX['object'], $EX['called_scope']) = array_pop($EX['arg_types_stack']); 1770 break; 1771 // }}} 1772 case XC_VERIFY_ABSTRACT_CLASS: // {{{ 1773 //unset($T[$op1['var']]); 1774 break; 1775 // }}} 1776 case XC_DECLARE_CLASS: 1777 case XC_DECLARE_INHERITED_CLASS: 1778 case XC_DECLARE_INHERITED_CLASS_DELAYED: // {{{ 1779 $key = $op1['constant']; 1780 if (!isset($this->dc['class_table'][$key])) { 1781 echo 'class not found: ', $key, 'existing classes are:', "\n"; 1782 var_dump(array_keys($this->dc['class_table'])); 1783 exit; 1784 } 1785 $class = &$this->dc['class_table'][$key]; 1786 if (!isset($class['name'])) { 1787 $class['name'] = unquoteName($this->getOpVal($op2, $EX), $EX); 1788 } 1789 if ($opc == XC_DECLARE_INHERITED_CLASS || $opc == XC_DECLARE_INHERITED_CLASS_DELAYED) { 1790 $ext /= XC_SIZEOF_TEMP_VARIABLE; 1791 $class['parent'] = $T[$ext]; 1792 unset($T[$ext]); 1843 } 1844 if (str($op1val) == "''") { 1845 $rvalue = $op2val; 1846 } 1847 else if (str($op2val) == "''") { 1848 $rvalue = $op1val; 1849 } 1850 else { 1851 $rvalue = str($op1val) . ' . ' . str($op2val); 1852 } 1853 $resvar = $rvalue; 1854 // }}} 1855 break; 1856 case XC_PRINT: // {{{ 1857 $op1val = $this->getOpVal($op1, $EX); 1858 $resvar = "print(" . str($op1val) . ")"; 1859 break; 1860 // }}} 1861 case XC_ECHO: // {{{ 1862 $op1val = $this->getOpVal($op1, $EX); 1863 $resvar = "echo " . str($op1val); 1864 break; 1865 // }}} 1866 case XC_EXIT: // {{{ 1867 $op1val = $this->getOpVal($op1, $EX); 1868 $resvar = "exit($op1val)"; 1869 break; 1870 // }}} 1871 case XC_INIT_ARRAY: 1872 case XC_ADD_ARRAY_ELEMENT: // {{{ 1873 $rvalue = $this->getOpVal($op1, $EX, false, true); 1874 1875 if ($opc == XC_ADD_ARRAY_ELEMENT) { 1876 $assoc = $this->getOpVal($op2, $EX); 1877 if (isset($assoc)) { 1878 $curResVar->value[] = array($assoc, $rvalue); 1793 1879 } 1794 1880 else { 1795 $c lass['parent'] = null;1796 } 1797 1798 for (;;){1799 if ($i + 1 <= $range[1]1800 && $opcodes[$i + 1]['opcode'] == XC_ADD_INTERFACE1801 && $opcodes[$i + 1]['op1']['var'] == $res['var']) {1802 // continue1881 $curResVar->value[] = array(null, $rvalue); 1882 } 1883 } 1884 else { 1885 if ($opc == XC_INIT_ARRAY) { 1886 $resvar = new Decompiler_Array(); 1887 if (!isset($rvalue)) { 1888 continue; 1803 1889 } 1804 else if ($i + 2 <= $range[1] 1805 && $opcodes[$i + 2]['opcode'] == XC_ADD_INTERFACE 1806 && $opcodes[$i + 2]['op1']['var'] == $res['var'] 1807 && $opcodes[$i + 1]['opcode'] == XC_FETCH_CLASS) { 1808 // continue 1809 } 1810 else { 1811 break; 1812 } 1813 $this->usedOps[XC_ADD_INTERFACE] = true; 1814 1815 $fetchop = &$opcodes[$i + 1]; 1816 $interface = $this->stripNamespace(unquoteName($this->getOpVal($fetchop['op2'], $EX), $EX)); 1817 $addop = &$opcodes[$i + 2]; 1818 $class['interfaces'][$addop['extended_value']] = $interface; 1819 unset($fetchop, $addop); 1820 $i += 2; 1821 } 1822 $this->dclass($class); 1823 echo "\n"; 1824 unset($class); 1825 break; 1826 // }}} 1827 case XC_INIT_STRING: // {{{ 1828 $resvar = "''"; 1829 break; 1830 // }}} 1831 case XC_ADD_CHAR: 1832 case XC_ADD_STRING: 1833 case XC_ADD_VAR: // {{{ 1834 $op1val = $this->getOpVal($op1, $EX); 1835 $op2val = $this->getOpVal($op2, $EX); 1836 switch ($opc) { 1837 case XC_ADD_CHAR: 1838 $op2val = value(chr(str($op2val))); 1839 break; 1840 case XC_ADD_STRING: 1841 break; 1842 case XC_ADD_VAR: 1843 break; 1844 } 1845 if (str($op1val) == "''") { 1846 $rvalue = $op2val; 1847 } 1848 else if (str($op2val) == "''") { 1849 $rvalue = $op1val; 1890 } 1891 1892 $assoc = $this->getOpVal($op2, $EX); 1893 if (isset($assoc)) { 1894 $resvar->value[] = array($assoc, $rvalue); 1850 1895 } 1851 1896 else { 1852 $rvalue = str($op1val) . ' . ' . str($op2val); 1853 } 1897 $resvar->value[] = array(null, $rvalue); 1898 } 1899 } 1900 break; 1901 // }}} 1902 case XC_QM_ASSIGN: // {{{ 1903 if (isset($curResVar) && is_a($curResVar, 'Decompiler_Binop')) { 1904 $curResVar->op2 = $this->getOpVal($op1, $EX); 1905 } 1906 else { 1907 $resvar = $this->getOpVal($op1, $EX); 1908 } 1909 break; 1910 // }}} 1911 case XC_BOOL: // {{{ 1912 $resvar = /*'(bool) ' .*/ $this->getOpVal($op1, $EX); 1913 break; 1914 // }}} 1915 case XC_RETURN: // {{{ 1916 $resvar = "return " . str($this->getOpVal($op1, $EX)); 1917 break; 1918 // }}} 1919 case XC_INCLUDE_OR_EVAL: // {{{ 1920 $type = $op2['var']; // hack 1921 $keyword = $this->includeTypes[$type]; 1922 $resvar = "$keyword " . str($this->getOpVal($op1, $EX)); 1923 break; 1924 // }}} 1925 case XC_FE_RESET: // {{{ 1926 $resvar = $this->getOpVal($op1, $EX); 1927 break; 1928 // }}} 1929 case XC_FE_FETCH: // {{{ 1930 $op['fe_src'] = $this->getOpVal($op1, $EX, false, true); 1931 $fe = new Decompiler_ForeachBox($op); 1932 $fe->iskey = false; 1933 $T[$res['var']] = $fe; 1934 1935 ++ $i; 1936 if (($ext & ZEND_FE_FETCH_WITH_KEY)) { 1937 $fe = new Decompiler_ForeachBox($op); 1938 $fe->iskey = true; 1939 1940 $res = $opcodes[$i]['result']; 1941 $T[$res['var']] = $fe; 1942 } 1943 break; 1944 // }}} 1945 case XC_SWITCH_FREE: // {{{ 1946 break; 1947 // }}} 1948 case XC_FREE: // {{{ 1949 $free = $T[$op1['var']]; 1950 if (!is_a($free, 'Decompiler_Array') && !is_a($free, 'Decompiler_Box')) { 1951 $op['php'] = is_object($free) ? $free : $this->unquote($free, '(', ')'); 1952 $lastphpop = &$op; 1953 } 1954 unset($T[$op1['var']], $free); 1955 break; 1956 // }}} 1957 case XC_JMP_NO_CTOR: 1958 break; 1959 case XC_JMP_SET: // ?: 1960 $resvar = new Decompiler_Binop($this, $this->getOpVal($op1, $EX), XC_JMP_SET, null); 1961 break; 1962 case XC_JMPNZ: // while 1963 case XC_JMPZNZ: // for 1964 case XC_JMPZ_EX: // and 1965 case XC_JMPNZ_EX: // or 1966 case XC_JMPZ: // {{{ 1967 if ($opc == XC_JMP_NO_CTOR && $EX['object']) { 1968 $rvalue = $EX['object']; 1969 } 1970 else { 1971 $rvalue = $this->getOpVal($op1, $EX); 1972 } 1973 1974 if (isset($op['cond_true'])) { 1975 // any true comes here, so it's a "or" 1976 $rvalue = implode(' or ', $op['cond_true']) . ' or ' . $rvalue; 1977 unset($op['cond_true']); 1978 } 1979 if (isset($op['cond_false'])) { 1980 echo "TODO(cond_false):\n"; 1981 var_dump($op);// exit; 1982 } 1983 if ($opc == XC_JMPZ_EX || $opc == XC_JMPNZ_EX) { 1984 $targetop = &$EX['opcodes'][$op2['opline_num']]; 1985 if ($opc == XC_JMPNZ_EX) { 1986 $targetop['cond_true'][] = foldToCode($rvalue, $EX); 1987 } 1988 else { 1989 $targetop['cond_false'][] = foldToCode($rvalue, $EX); 1990 } 1991 unset($targetop); 1992 } 1993 else { 1994 $op['cond'] = $rvalue; 1995 $op['isjmp'] = true; 1996 } 1997 break; 1998 // }}} 1999 case XC_CONT: 2000 case XC_BRK: 2001 $op['cond'] = null; 2002 $op['isjmp'] = true; 2003 $resvar = $opc == XC_CONT ? 'continue' : 'break'; 2004 $count = str($this->getOpVal($op2, $EX)); 2005 if ($count != '1') { 2006 $resvar .= ' ' . $count; 2007 } 2008 break; 2009 case XC_GOTO: 2010 $resvar = 'goto label' . $op['op1']['var']; 2011 $istmpres = false; 2012 break; 2013 2014 case XC_JMP: // {{{ 2015 $op['cond'] = null; 2016 $op['isjmp'] = true; 2017 break; 2018 // }}} 2019 case XC_CASE: 2020 // $switchValue = $this->getOpVal($op1, $EX); 2021 $caseValue = $this->getOpVal($op2, $EX); 2022 $resvar = $caseValue; 2023 break; 2024 case XC_RECV_INIT: 2025 case XC_RECV: 2026 $offset = $this->getOpVal($op1, $EX); 2027 $lvalue = $this->getOpVal($op['result'], $EX); 2028 if ($opc == XC_RECV_INIT) { 2029 $default = value($op['op2']['constant']); 2030 } 2031 else { 2032 $default = null; 2033 } 2034 $EX['recvs'][str($offset)] = array($lvalue, $default); 2035 break; 2036 case XC_POST_DEC: 2037 case XC_POST_INC: 2038 case XC_POST_DEC_OBJ: 2039 case XC_POST_INC_OBJ: 2040 case XC_PRE_DEC: 2041 case XC_PRE_INC: 2042 case XC_PRE_DEC_OBJ: 2043 case XC_PRE_INC_OBJ: // {{{ 2044 $flags = array_flip(explode('_', $opname)); 2045 if (isset($flags['OBJ'])) { 2046 $resvar = $this->getOpVal($op1, $EX) . '->' . unquoteVariableName($this->getOpVal($op2, $EX), $EX); 2047 } 2048 else { 2049 $resvar = $this->getOpVal($op1, $EX); 2050 } 2051 $opstr = isset($flags['DEC']) ? '--' : '++'; 2052 if (isset($flags['POST'])) { 2053 $resvar .= $opstr; 2054 } 2055 else { 2056 $resvar = "$opstr$resvar"; 2057 } 2058 break; 2059 // }}} 2060 2061 case XC_BEGIN_SILENCE: // {{{ 2062 $EX['silence'] ++; 2063 break; 2064 // }}} 2065 case XC_END_SILENCE: // {{{ 2066 $EX['silence'] --; 2067 $lastresvar = '@' . str($lastresvar, $EX); 2068 break; 2069 // }}} 2070 case XC_CAST: // {{{ 2071 $type = $ext; 2072 static $type2cast = array( 2073 IS_LONG => '(int)', 2074 IS_DOUBLE => '(double)', 2075 IS_STRING => '(string)', 2076 IS_ARRAY => '(array)', 2077 IS_OBJECT => '(object)', 2078 IS_BOOL => '(bool)', 2079 IS_NULL => '(unset)', 2080 ); 2081 assert(isset($type2cast[$type])); 2082 $cast = $type2cast[$type]; 2083 $resvar = $cast . ' ' . $this->getOpVal($op1, $EX); 2084 break; 2085 // }}} 2086 case XC_EXT_STMT: 2087 case XC_EXT_FCALL_BEGIN: 2088 case XC_EXT_FCALL_END: 2089 case XC_EXT_NOP: 2090 break; 2091 case XC_DECLARE_FUNCTION: 2092 $this->dfunction($this->dc['function_table'][$op1['constant']], $EX['indent']); 2093 break; 2094 case XC_DECLARE_LAMBDA_FUNCTION: // {{{ 2095 ob_start(); 2096 $this->dfunction($this->dc['function_table'][$op1['constant']], $EX['indent']); 2097 $resvar = ob_get_clean(); 2098 $istmpres = true; 2099 break; 2100 // }}} 2101 case XC_DECLARE_CONST: 2102 $name = $this->stripNamespace(unquoteName($this->getOpVal($op1, $EX), $EX)); 2103 $value = str($this->getOpVal($op2, $EX)); 2104 $resvar = 'const ' . $name . ' = ' . $value; 2105 break; 2106 case XC_DECLARE_FUNCTION_OR_CLASS: 2107 /* always removed by compiler */ 2108 break; 2109 case XC_TICKS: 2110 $lastphpop['ticks'] = $this->getOpVal($op1, $EX); 2111 // $EX['tickschanged'] = true; 2112 break; 2113 case XC_RAISE_ABSTRACT_ERROR: 2114 // abstract function body is empty, don't need this code 2115 break; 2116 case XC_USER_OPCODE: 2117 echo '// ZEND_USER_OPCODE, impossible to decompile'; 2118 break; 2119 case XC_OP_DATA: 2120 break; 2121 default: // {{{ 2122 $call = array(&$this, $opname); 2123 if (is_callable($call)) { 2124 $this->usedOps[$opc] = true; 2125 $this->{$opname}($op, $EX); 2126 } 2127 else if (isset($this->binops[$opc])) { // {{{ 2128 $this->usedOps[$opc] = true; 2129 $op1val = $this->getOpVal($op1, $EX, false); 2130 $op2val = $this->getOpVal($op2, $EX, false); 2131 $rvalue = new Decompiler_Binop($this, $op1val, $opc, $op2val); 1854 2132 $resvar = $rvalue; 1855 2133 // }}} 1856 break; 1857 case XC_PRINT: // {{{ 2134 } 2135 else if (isset($this->unaryops[$opc])) { // {{{ 2136 $this->usedOps[$opc] = true; 1858 2137 $op1val = $this->getOpVal($op1, $EX); 1859 $resvar = "print(" . str($op1val) . ")"; 1860 break; 2138 $myop = $this->unaryops[$opc]; 2139 $rvalue = $myop . str($op1val); 2140 $resvar = $rvalue; 1861 2141 // }}} 1862 case XC_ECHO: // {{{ 1863 $op1val = $this->getOpVal($op1, $EX); 1864 $resvar = "echo " . str($op1val); 1865 break; 1866 // }}} 1867 case XC_EXIT: // {{{ 1868 $op1val = $this->getOpVal($op1, $EX); 1869 $resvar = "exit($op1val)"; 1870 break; 1871 // }}} 1872 case XC_INIT_ARRAY: 1873 case XC_ADD_ARRAY_ELEMENT: // {{{ 1874 $rvalue = $this->getOpVal($op1, $EX, false, true); 1875 1876 if ($opc == XC_ADD_ARRAY_ELEMENT) { 1877 $assoc = $this->getOpVal($op2, $EX); 1878 if (isset($assoc)) { 1879 $curResVar->value[] = array($assoc, $rvalue); 1880 } 1881 else { 1882 $curResVar->value[] = array(null, $rvalue); 1883 } 1884 } 1885 else { 1886 if ($opc == XC_INIT_ARRAY) { 1887 $resvar = new Decompiler_Array(); 1888 if (!isset($rvalue)) { 1889 continue; 1890 } 1891 } 1892 1893 $assoc = $this->getOpVal($op2, $EX); 1894 if (isset($assoc)) { 1895 $resvar->value[] = array($assoc, $rvalue); 1896 } 1897 else { 1898 $resvar->value[] = array(null, $rvalue); 1899 } 1900 } 1901 break; 1902 // }}} 1903 case XC_QM_ASSIGN: // {{{ 1904 if (isset($curResVar) && is_a($curResVar, 'Decompiler_Binop')) { 1905 $curResVar->op2 = $this->getOpVal($op1, $EX); 1906 } 1907 else { 1908 $resvar = $this->getOpVal($op1, $EX); 1909 } 1910 break; 1911 // }}} 1912 case XC_BOOL: // {{{ 1913 $resvar = /*'(bool) ' .*/ $this->getOpVal($op1, $EX); 1914 break; 1915 // }}} 1916 case XC_RETURN: // {{{ 1917 $resvar = "return " . str($this->getOpVal($op1, $EX)); 1918 break; 1919 // }}} 1920 case XC_INCLUDE_OR_EVAL: // {{{ 1921 $type = $op2['var']; // hack 1922 $keyword = $this->includeTypes[$type]; 1923 $resvar = "$keyword " . str($this->getOpVal($op1, $EX)); 1924 break; 1925 // }}} 1926 case XC_FE_RESET: // {{{ 1927 $resvar = $this->getOpVal($op1, $EX); 1928 break; 1929 // }}} 1930 case XC_FE_FETCH: // {{{ 1931 $op['fe_src'] = $this->getOpVal($op1, $EX, false, true); 1932 $fe = new Decompiler_ForeachBox($op); 1933 $fe->iskey = false; 1934 $T[$res['var']] = $fe; 1935 1936 ++ $i; 1937 if (($ext & ZEND_FE_FETCH_WITH_KEY)) { 1938 $fe = new Decompiler_ForeachBox($op); 1939 $fe->iskey = true; 1940 1941 $res = $opcodes[$i]['result']; 1942 $T[$res['var']] = $fe; 1943 } 1944 break; 1945 // }}} 1946 case XC_SWITCH_FREE: // {{{ 1947 break; 1948 // }}} 1949 case XC_FREE: // {{{ 1950 $free = $T[$op1['var']]; 1951 if (!is_a($free, 'Decompiler_Array') && !is_a($free, 'Decompiler_Box')) { 1952 $op['php'] = is_object($free) ? $free : $this->unquote($free, '(', ')'); 1953 $lastphpop = &$op; 1954 } 1955 unset($T[$op1['var']], $free); 1956 break; 1957 // }}} 1958 case XC_JMP_NO_CTOR: 1959 break; 1960 case XC_JMP_SET: // ?: 1961 $resvar = new Decompiler_Binop($this, $this->getOpVal($op1, $EX), XC_JMP_SET, null); 1962 break; 1963 case XC_JMPNZ: // while 1964 case XC_JMPZNZ: // for 1965 case XC_JMPZ_EX: // and 1966 case XC_JMPNZ_EX: // or 1967 case XC_JMPZ: // {{{ 1968 if ($opc == XC_JMP_NO_CTOR && $EX['object']) { 1969 $rvalue = $EX['object']; 1970 } 1971 else { 1972 $rvalue = $this->getOpVal($op1, $EX); 1973 } 1974 1975 if (isset($op['cond_true'])) { 1976 // any true comes here, so it's a "or" 1977 $rvalue = implode(' or ', $op['cond_true']) . ' or ' . $rvalue; 1978 unset($op['cond_true']); 1979 } 1980 if (isset($op['cond_false'])) { 1981 echo "TODO(cond_false):\n"; 1982 var_dump($op);// exit; 1983 } 1984 if ($opc == XC_JMPZ_EX || $opc == XC_JMPNZ_EX) { 1985 $targetop = &$EX['opcodes'][$op2['opline_num']]; 1986 if ($opc == XC_JMPNZ_EX) { 1987 $targetop['cond_true'][] = foldToCode($rvalue, $EX); 1988 } 1989 else { 1990 $targetop['cond_false'][] = foldToCode($rvalue, $EX); 1991 } 1992 unset($targetop); 1993 } 1994 else { 1995 $op['cond'] = $rvalue; 1996 $op['isjmp'] = true; 1997 } 1998 break; 1999 // }}} 2000 case XC_CONT: 2001 case XC_BRK: 2002 $op['cond'] = null; 2003 $op['isjmp'] = true; 2004 $resvar = $opc == XC_CONT ? 'continue' : 'break'; 2005 $count = str($this->getOpVal($op2, $EX)); 2006 if ($count != '1') { 2007 $resvar .= ' ' . $count; 2008 } 2009 break; 2010 case XC_GOTO: 2011 $resvar = 'goto label' . $op['op1']['var']; 2012 $istmpres = false; 2013 break; 2014 2015 case XC_JMP: // {{{ 2016 $op['cond'] = null; 2017 $op['isjmp'] = true; 2018 break; 2019 // }}} 2020 case XC_CASE: 2021 // $switchValue = $this->getOpVal($op1, $EX); 2022 $caseValue = $this->getOpVal($op2, $EX); 2023 $resvar = $caseValue; 2024 break; 2025 case XC_RECV_INIT: 2026 case XC_RECV: 2027 $offset = $this->getOpVal($op1, $EX); 2028 $lvalue = $this->getOpVal($op['result'], $EX); 2029 if ($opc == XC_RECV_INIT) { 2030 $default = value($op['op2']['constant']); 2031 } 2032 else { 2033 $default = null; 2034 } 2035 $EX['recvs'][str($offset)] = array($lvalue, $default); 2036 break; 2037 case XC_POST_DEC: 2038 case XC_POST_INC: 2039 case XC_POST_DEC_OBJ: 2040 case XC_POST_INC_OBJ: 2041 case XC_PRE_DEC: 2042 case XC_PRE_INC: 2043 case XC_PRE_DEC_OBJ: 2044 case XC_PRE_INC_OBJ: // {{{ 2045 $flags = array_flip(explode('_', $opname)); 2046 if (isset($flags['OBJ'])) { 2047 $resvar = $this->getOpVal($op1, $EX) . '->' . unquoteVariableName($this->getOpVal($op2, $EX), $EX); 2048 } 2049 else { 2050 $resvar = $this->getOpVal($op1, $EX); 2051 } 2052 $opstr = isset($flags['DEC']) ? '--' : '++'; 2053 if (isset($flags['POST'])) { 2054 $resvar .= $opstr; 2055 } 2056 else { 2057 $resvar = "$opstr$resvar"; 2058 } 2059 break; 2060 // }}} 2061 2062 case XC_BEGIN_SILENCE: // {{{ 2063 $EX['silence'] ++; 2064 break; 2065 // }}} 2066 case XC_END_SILENCE: // {{{ 2067 $EX['silence'] --; 2068 $lastresvar = '@' . str($lastresvar, $EX); 2069 break; 2070 // }}} 2071 case XC_CAST: // {{{ 2072 $type = $ext; 2073 static $type2cast = array( 2074 IS_LONG => '(int)', 2075 IS_DOUBLE => '(double)', 2076 IS_STRING => '(string)', 2077 IS_ARRAY => '(array)', 2078 IS_OBJECT => '(object)', 2079 IS_BOOL => '(bool)', 2080 IS_NULL => '(unset)', 2081 ); 2082 assert(isset($type2cast[$type])); 2083 $cast = $type2cast[$type]; 2084 $resvar = $cast . ' ' . $this->getOpVal($op1, $EX); 2085 break; 2086 // }}} 2087 case XC_EXT_STMT: 2088 case XC_EXT_FCALL_BEGIN: 2089 case XC_EXT_FCALL_END: 2090 case XC_EXT_NOP: 2091 break; 2092 case XC_DECLARE_FUNCTION: 2093 $this->dfunction($this->dc['function_table'][$op1['constant']], $EX['indent']); 2094 break; 2095 case XC_DECLARE_LAMBDA_FUNCTION: // {{{ 2096 ob_start(); 2097 $this->dfunction($this->dc['function_table'][$op1['constant']], $EX['indent']); 2098 $resvar = ob_get_clean(); 2099 $istmpres = true; 2100 break; 2101 // }}} 2102 case XC_DECLARE_CONST: 2103 $name = $this->stripNamespace(unquoteName($this->getOpVal($op1, $EX), $EX)); 2104 $value = str($this->getOpVal($op2, $EX)); 2105 $resvar = 'const ' . $name . ' = ' . $value; 2106 break; 2107 case XC_DECLARE_FUNCTION_OR_CLASS: 2108 /* always removed by compiler */ 2109 break; 2110 case XC_TICKS: 2111 $lastphpop['ticks'] = $this->getOpVal($op1, $EX); 2112 // $EX['tickschanged'] = true; 2113 break; 2114 case XC_RAISE_ABSTRACT_ERROR: 2115 // abstract function body is empty, don't need this code 2116 break; 2117 case XC_USER_OPCODE: 2118 echo '// ZEND_USER_OPCODE, impossible to decompile'; 2119 break; 2120 case XC_OP_DATA: 2121 break; 2122 default: // {{{ 2123 echo "\x1B[31m * TODO ", $opname, "\x1B[0m\n"; 2124 $covered = false; 2125 // }}} 2126 } 2127 if ($covered) { 2128 $this->usedOps[$opc] = true; 2129 } 2130 } 2142 } 2143 else { 2144 $notHandled = true; 2145 } 2146 // }}} 2147 } 2148 if ($notHandled) { 2149 echo "\x1B[31m * TODO ", $opname, "\x1B[0m\n"; 2150 } 2151 else { 2152 $this->usedOps[$opc] = true; 2153 } 2154 2131 2155 if (isset($resvar)) { 2132 2156 if ($istmpres) {
Note: See TracChangeset
for help on using the changeset viewer.

