Skip to content

Latest commit

 

History

History
1142 lines (1142 loc) · 33.2 KB

zend_op_array.md

File metadata and controls

1142 lines (1142 loc) · 33.2 KB

Zend_Op_Array

Modify by:MG193.7

My Blog

My Github

Base on vld document

Opcode name Explanation Example (phpdbg)
NOP no operation NOP
ADD Adds "value1" to "value2" and stores the result into "result". ADD 1 2 ~0
$a = 1+2;
SUB Subtracts "value2" from "value1" and stores the result into "result". SUB 2 1 ~0
$a = 2-1;
MUL Multiplys "value1" by "value2" and stores the result into "result". MUL 1 2 ~0
$a = 1*2;
DIV Divides "value1" by "value2" and stores the result into "result". DIV 6 3 ~0
$a = 6/3;
MOD Makes the value of "result" congruent to "value1" modulo "value2". MOD 6 3 ~0
$a = 6%3;
SL Shift bits of value1 to the left value2 steps (each step means "multiply by two") SL 8 2 ~0
$a = 8<<2;
SR Shift bits of value1 to the right value2 steps (each step means "divide by two") SR 8 2 ~0
$a = 8>>2;
CONCAT Concats string values string1 and string2 CONCAT "A" "B" ~0
echo "A"."B";
BW_OR Bit-wise or of value1 and value2 BW_OR 1 2 ~0
echo 1|2;
BW_AND Bit-wise and of value1 and value2 BW_AND 1 2 ~0
echo 1&2;
BW_XOR Bit-wise xor of value1 and value2 BW_XOR 1 2 ~0
echo 1^2;
BW_NOT Bit-wise not of "value" BW_NOT 15 ~0
echo ~15;
BOOL_NOT Boolean (logical) not of "value" BOOL_NOT 1 ~0
echo !1;
BOOL_XOR Boolean (logical) xor of value1 BOOL 1 2 ~0
echo 1 xor 2;
IS_IDENTICAL Compares value1 and value2 to see if they are equal AND have the same type IS_IDENTICAL 1 1 ~0
echo (1===1);
IS_NOT_IDENTICAL compares value1 and value2 to see if they are unequal or of different types IS_NOT_IDENTICAL 1 1 ~0
echo (1!==1);
IS_EQUAL compares if value1 and value2 are equal IS_EQUAL 1 1 ~0
echo (1==1);
IS_NOT_EQUAL compares if value1 and value2 are not equal IS_NOT_EQUAL 1 1 ~0
echo (1!=1);
IS_SMALLER compares if value1 is less than value2 IS_SMALLER1 1 2 ~0
echo (1 < 2);
IS_SMALLER_OR_EQUAL compares if value1 is less than or equal to value2 IS_SMALLER_OR_EQUAL 2 1 ~0
echo (2<=1);
CAST casts value1 as type value2 (type in extended_value) CAST<4> 1 ~0
echo (int)1;
QM_ASSIGN Question Mark Assign, used twice inside a question mark assign to temporarily assign result as value1 (this is followed up with an ASSIGN bytecode) JMPZ 1 J3
QM_ASSIGN 1 ~0
JMP J4
QM_ASSIGN 2 ~0
ECHO ~0
echo (1?1:2);
ASSIGN_ADD Add value1 to value2 and store in variable indicated by value1 ASSIGN_ADD $a 2
$a+=2;
ASSIGN_SUB Subtract value1 from value2 and store in variable indicated by value1 ASSIGN_SUB $a 2
$a-=2;
ASSIGN_MUL Multiply result by value1 and store in variable indicated by result ASSIGN_MUL $a 2
$a*=2;
ASSIGN_DIV Divide result by value1and store in variable indicated by result. ASSIGN_DIV $a 2
$a/=2;
ASSIGN_MOD Perform result mod value1 and store in variable indicated by result ASSIGN_MOD $a 2
$a%=2;
ASSIGN_SL Shift result by value1 bits to left and store in variable indicated by result ASSIGN_SL $a 2
$a<<=2;
ASSIGN_SR Shift result by value1 bits to right and store in variable indicated by result ASSIGN_SR $a 2
$a>>=2;
ASSIGN_CONCAT Concats string values result and value1 and store in variable indicated by result ASSIGN_CONCAT $a 'z'
$a.='z';
ASSIGN_BW_OR Performs binary OR on result and value1 and stores in variable indicated by result. ASSIGN_BW_OR $a 64
$a|=64;
ASSIGN_BW_AND Performs binary AND on result and value1 and stores in variable indicated by result. ASSIGN_BW_AND $a 64
$a &=64;
ASSIGN_BW_XOR Performs binary XOR on result and value1and stores in variable indicated by result. ASSIGN_BW_XOR $a 64
$a ^=64;
PRE_INC increments variable indicated by value1 by 1 (before performing other operations) and stores in result PRE_INC $a
++$a;
PRE_DEC decrements variable indicated by value1 by 1 (before performing other operations) and stores in results PRE_DEC $a
--$a;
POST_INC increments variable indicated by value1 by 1 (after performing other operations) and stores in result POST_INC $a ~0
$a++;
POST_DEC decrements variable indicated by value1 by 1 (after performing other operations) and stores in result POST_DEC $a ~0
$a--;
ASSIGN assigns value1 to result ASSIGN $a $b
$a=$b;
ASSIGN_REF UNKNOW in phpdbg.
Maybe you could refer to ASSIGN_REF
UNKNOW
ECHO Dump text ECHO "hello world"
echo "hello world";
PRINT Same as ECHO? ECHO<1> "hello world"
print 'hello world';
If you want to refer the opcodes in vld,
you could see PRINT
JMP Unconditonally jump to the address #0 IS_EQUAL $a "a" ~0
#1 JMPZ ~0 J4
#2 ECHO 1
#3 JMP J5
#4 ECHO 2
#5 RETURN<-1> 1

if($a=="a"){echo 1;}else{echo 2;}
JMPZ Jump to the address if the value is zero You could see the opcodes in JMP
JMPNZ Jump to the address if the value is not zero ...
JMPNZ ~0 JX
...

if($b!=0){...}
JMPZNZ Jump to the address given in the operands if the value is zero;
jump to the address given in extended data if nonzero.
UNKNOW in phpdbg
You could refer to JMPZNZ
JMPZ_EX Jump to the address if the value is zero. #0 JMPZ_EX $a J2 ~0
#1 BOOL true ~0
#2 JMPZ ~0
#3 RETURN<-1> 1

if($a&&true){}
JMPNZ_EX Jump to the address if the value is not zero. #0 JMPZ_EX $a J2 ~0
#1 BOOL true ~0
#2 JMPZ ~0
#3 RETURN<-1> 1

if($a||true){}
CASE UNKNOW Do not found CASE opcode in phpdbg,
You could refer to CASE
SWITCH_FREE Release the allocated space of "value"? Do not found SWITCH_FREE in phpdbg,
You could refer to SWITCH_FREE
BRK It means "break" in vld,
But not found this opcode in phpdbg.
If you want to break in while-loop(or something else),phpdbg will simply use JMP opcode jump out the loop,instead of use "BRK" opcode.
#0 JMP J2
#1 JMP J3
#2 JMPNZ 1 J1
#3 RETURN<-1> 1

while(1){break;}
You also could see BRK
CONT Same as BRK opcode,
this opcode means "continue" in vld,
But not found this opcode in phpdbg.
phpdbg still use JMP to control the flow in loop.
You could refer to CONT
BOOL convert value to boolean and store in result #0 JMPZ_EX $a J2 ~0
#1 BOOL true ~0
#2 JMPZ ~0
#3 RETURN<-1> 1

if($a&&true){}
ROPE_INIT when create a string that cotains variable,
this opcode used to init this string and store the string of begining part to result
ROPE_INIT<3> "Test" ~1
ROPE_ADD<1> ~1 $a ~1
ROPE_END<2> ~1 " Test" ~0
ECHO ~0

echo "Test$a Test";
ROPE_ADD after ROPE_INIT opcode,continue add a variable to string,and store the string to result. Could see ROPE_INIT part
ROPE_END after ROPE_INIT opcode,continue add a string to the whole string,and treat the string just added as the end of the whole string. Could see ROPE_INIT part
FAST_CONCAT concats value1 and value2,than stored it to the result FAST_CONCAT "Test" $a ~0
ECHO ~0

echo "Test$a";
BEGIN_SILENCE prepare to perform function call without displaying error messages BEGIN_SILENCE ~0
INIT_FCALL<1> 96 "file"
SEND_VAL"non_existent_file" 1
DO_ICALL @1
END_SILENCE ~0
ASSIGN $a @1
RETURN<-1> 1

$a = @file("non_existent_file");
END_SILENCE no longer surpress error messages See BEGIN_SILENCE part
INIT_FCALL init a function going to call INIT_FCALL<1> 96 "abs"
SEND_VAL 2 1
DO_ICALL

abs(2);
INIT_DYNAMIC_CALL call to function dynamicly ASSIGN $x "phpinfo"
INIT_DYNAMIC_CALL $x
DO_FCALL

$x = 'phpinfo';
$x();
INIT_FCALL_BY_NAME call to function INIT_FCALL_BY_NAME "test"
DO_FCALL @1
ASSIGN $a @1

$a = test();
DO_FCALL Call a function.
If the result of called function was stored to a variable,this opcode must take a result!
See INIT_DYNAMIC_CALL and INIT_FCALL_BY_NAME part
DO_FCALL_BY_NAME Call a function by name. UNKNOW in phpdbg,
You could see DO_FCALL_BY_NAME
RETURN Return value from a funciton. RETURN 1
return 1;
RECV Receive the number of functoin arguments RECV 1 $a
RETURN<-1> null

function test($a){}
RECV_INIT Initialize a function argument with "value" if not received from caller.
Otherwise same as RECV.
RECV_INIT 1 "test" $t
RETURN<-1> null

function a($t="test"){}
SEND_VAL Pass the constant value as an actual parameter to a function. INIT_FCALL<2> 112 "hello"
SEND_VAL "world" 1
SEND_VAL "ok" 2
DO_FCALL

hello("world","ok");
SEND_VAL_EX Pass the constant value as an actual parameter to a function.Same as SEND_VAL_EX INIT_FCALL_BY_NAME<2> "hello"
SEND_VAL_EX "world" 1
SEND_VAL_EX "ok" 2
DO_FCALL

hello("world","ok");
SEND_VAR Pass the variable value as an actual parameter to a function. ASSIGN $a 1
INIT_FCALL<1> 96 "abs"
SEND_VAR $a 1
DO_ICALL

$a=1;abs($a);
SEND_VAR_EX Pass the variable value as an actual parameter to a function.Same as SEND_VAR. ASSIGN $a 1
INIT_FCALL_BY_NAME<1> "test"
SEND_VAR_EX $a 1
DO_ICALL

$a=1;test($a);
SEND_REF Pass the reference value as an actual parameter to a function. INIT_FCALL<1> 96 "each"
SEND_REF $a 1
DO_ICALL

@each($a);
NEW Construct an instance of "type" and store the reference to the object into "result". NEW<2> "A" @1
SEND_VAL_EX "a" 1
DO_FCALL
FREE @1

new A("a");
INIT_NS_FCALL_BY_NAME No sample in vld or phpdbg. UNKNOW
FREE Release the allocated space of the value. Could see NEW part
INIT_ARRAY Allocate a new array with elem-value as the first element of the array. UNKNOW in phpdbg,
You could refer to INIT_ARRAY
ADD_ARRAY_ELEMENT Add elem-value as an element to array-value UNKNOW in phpdbg,
You could refer to ADD_ARRAY_ELEMENT
INCLUDE_OR_EVAL Include the file specified by filename and eval it. INCLUDE_OR_EVAL<2> "test.php"
INCLUDE_OR_EVAL<1> "echo 1;"

include "test.php";
eval("echo 1;");
UNSET_CV Unset the variable. UNSET_CV $A
unset($A);
UNSET_VAR Unset the variable. ASSIGN $A "x"
UNSET_VAR<4> $A

$A="x";
unset($$A);
UNSET_DIM Unset the entry of array-value, which is specified by index UNSET_DIM $A 0
unset($A[0]);
UNSET_OBJ Unset the property of the current object UNSET_OBJ<8> $A "test"
unset($A->test);
FE_RESET_R Initialize an iterator on array-value. If the array is empty, jump to address. #0 ASSIGN $a array(3)
#1 FE_RESET_R $a J5 @1
#2 FE_FETCH_R<96> @1 $num
#3 ECHO<1> $num
#4 JMP J2
#5 FE_FREE @1

$a = array(1,2,3);
foreach($a as $num){
print $num;
}
FE_FETCH_R Fetch an element from iterator.
If no element is available, jump to the address that FE_RESET_R opcode setted.
Could see FE_RESET_R part.
EXIT Exit running after dumping "message". EXIT "foo"
die("foo");
FETCH_R fetch Variable variables. ASSIGN $a "x"
FETCH_R<4> $a ~1
ECHO ~1

$a="x";
echo $$a;
FETCH_DIM_R fetch value of variables by index. FETCH_R<4> $a ~1
FETCH_DIM_R ~1 0 ~2
ECHO ~2

echo $$a[0];

FETCH_DIM_R $x 0
$x[0];
FETCH_OBJ_R fetch property value of Variable variables FETCH_R<4> $a ~1
FETCH_OBJ_R ~1 "test" ~2
ECHO ~2

echo($$a->test);
FETCH_W fetch Variable variables and make it writable. ASSIGN $x 1
ASSIGN $a "x"
FETCH_W<4> $a @2
ASSIGN @2 2

$x=1;
$a="x";
$$a=2;
FETCH_DIM_W fetch Variable variables by index and make it writable. FETCH_DIM_W $x 0 @0
ASSIGN_DIM @0 1
OP_DATA 2

$x[0][1]=2;
FETCH_OBJ_W fetch property value of Variable variables and make it writable. FETCH_OBJ_W $x "t" @0
ASSIGN_OBJ<16> @0 "test"
OP_DATA 1

$x->t->test=1;
FETCH_RW fetch value of Variable variables. FETCH_RW<4> $a @0
POST_INC @0;

$$a++;
FETCH_DIM_RW fetch value of Variable variables by index. FETCH_DIM_RW $a 0 @0
POST_INC @0

$a[0]++;
FETCH_OBJ_RW fetch property value of Variable variables FETCH_OBJ_RW $a "b" @0
POST_INC_OBJ<16> @0 "c"

$a->b->c++;
FETCH_IS Fetch the value from variable which is to be used to test if it is set or not, through isset()/isempty(). FETCH_IS<2> "_GET" ~0
ISSET_ISEMPTY_DIM_OBJ ~0 0

isset($_GET[0]);
FETCH_DIM_IS No php sample.
FETCH_OBJ_IS No php sample.
FETCH_FUNC_ARG fetch value of Variable variables as arg of function INIT_FCALL_BY_NAME<1> "test"
CHECK_FUNC_ARG 1
FETCH_FUNC_ARG<4> $a @0
SEND_FUNC_ARG @0 1
DO_FCALL

test($$a);
FETCH_DIM_FUNC_ARG fetch value of variable by index as arg of function INIT_FCALL_BY_NAME<1> "test"
CHECK_FUNC_ARG 1
FETCH_DIM_FUNC_ARG $a 0 @0
SEND_FUNC_ARG @0 1
DO_FCALL

test($a[0]);
FETCH_OBJ_FUNC_ARG fetch property value of variable as arg of function INIT_FCALL_BY_NAME<1> "test"
CHECK_FUNC_ARG 1
FETCH_OBJ_FUNC_ARG $a "b" @0
SEND_FUNC_ARG @0 1
DO_FCALL

test($a->b);
FETCH_UNSET Fetch a variable for the purpose of unset() operation. FETCH_UNSET<4> $A @1
UNSET_DIM @1 0

unset($$A[0]);
FETCH_DIM_UNSET Fetch a variable by index for the purpose of unset() operation. FETCH_DIM_UNSET $a 0 @0
UNSET_OBJ @0 "b"

unset($a[0]->b);
FETCH_OBJ_UNSET Fetch a property value of variable for the purpose of unset() operation. FETCH_OBJ_UNSET $a "b" @0
UNSET_OBJ<16> @0 "c"

unset($a->b->c);
FETCH_LIST_R Fetch array list. FETCH_LIST_R array(2) 0 @0
ASSIGN $x @0
FETCH_LIST_R array(2) 1 @2
ASSIGN $b @2

list($x,$b) = array("x","b");
FETCH_DIM_TMP_VAR No php sample in phpdbg You could refer to FETCH_DIM_TMP_VAR
FETCH_CONSTANT fetch value by const name. FETCH_CONSTANT "A" ~0
ECHO ~0

echo A;
GOTO No sample in phpdbg and vld,
phpdbg use JMP opcode to control flow.
EXT_STMT No php sample
EXT_FCALL_BEGIN No php sample
EXT_FCALL_END No php sample
EXT_NOP No php sample
TICKS TICKS<100>
declare(ticks=100);
SEND_VAR_NO_REF No php sample
CATCH catch when Exception get throw. #0 THROW $t
#1 JMP J4
#2 CATCH<1> "A" $e
#3 ECHO "catch"
#4 RETURN<-1> 1

try{throw $t}
catch(A $e){echo "catch";}
THROW throw some Exception. THROW $t
throw $t;
FETCH_CLASS fetch static class FETCH_CLASS $obj @0
FETCH_CLASS_CONSTANT @0 "a"

$obj::a;
FETCH_CLASS_CONSTANT fetch static constant from class Could see FETCH_CLASS part.
FETCH_STATIC_PROP_R fetch static property value from class FETCH_CLASS $obj @0
FETCH_STATIC_PROP_R "a" @0 ~1

$obj::$a;
FETCH_STATIC_PROP_RW fetch static property value from class,same as FETCH_STATIC_PROP_R but make it readable and writable. FETCH_CLASS $obj @0
FETCH_STATIC_PROP_RW "a" @0 @1
POST_INC @1 ~2

$obj::$a++;
FETCH_STATIC_PROP_W fetch static property value from class AND make it writable. FETCH_CLASS $obj @0
FETCH_STATIC_PROP_W "a" @0 @1
ASSIGN @1 1

$obj::$a=1;
CLONE clone an object CLONE $t ~0
clone $t;
RETURN_BY_REF No sample in phpdbg
INIT_METHOD_CALL Prepare for a method call. Followed by DO_FCALL. INIT_METHOD_CALL $obj "a"
DO_FCALL

$obj->a();
INIT_STATIC_METHOD_CALL Prepare for a static method call. Followed by DO_FCALL. FETCH_CLASS $obj @0
INIT_STATIC_METHOD_CALL @0 "a"
DO_FCALL

$obj::a();
ISSET_ISEMPTY_CV check wether a variable is setted and store the result. ISSET_ISEMPTY_CV $a ~0
isset($a);
ISSET_ISEMPTY_VAR check wether a variable is setted and store the result. ISSET_ISEMPTY_VAR<4> $a ~0
isset($$a);
ISSET_ISEMPTY_DIM_OBJ check wether a variable is setted by its index and store the result. ISSET_ISEMPTY_DIM_OBJ $a 0 ~0
isset($a[0]);
ZEND_SEND_VAL_EX Could see SEND_VAL_EX part.
ZEND_SEND_VAR Could see SEND_VAR part.
ZEND_INIT_USER_CALL
ZEND_SEND_ARRAY
ZEND_SEND_USER
STRLEN get length of string and store the result STRLEN $a
strlen($a);
DEFINED
ZEND_TYPE_CHECK
ZEND_VERIFY_RETURN_TYPE
ZEND_FE_RESET_RW
ZEND_FE_FETCH_RW
ZEND_FE_FREE
ZEND_INIT_DYNAMIC_CALL
ZEND_DO_ICALL
ZEND_DO_UCALL
ZEND_DO_FCALL_BY_NAME
PRE_INC_OBJ Same as PRE_INC but operate to an object PRE_INC_OBJ $obj "a"
++$obj->a;
PRE_DEC_OBJ Same as PRE_DEC but operate to an object PRE_DEC_OBJ $obj "a"
--$obj->a;
POST_INC_OBJ Same as POST_INC but operate to an object POST_INC_OBJ $obj "a" ~0
$obj->a++;
POST_DEC_OBJ Same as POST_DEC but operate to an object POST_DEC_OBJ $obj "a" ~0
$obj->a--;
ASSIGN_OBJ fetch an object and wait for OP_DATA opcode. ASSIGN_OBJ $obj "a"
OP_DATA $t

$obj->a=$t;
INSTANCEOF INSTANCEOF $a "A" ~0
$a instanceof A;
DECLARE_CLASS declare a class by name JMPZ true JX
DECLARE_CLASS "a" @0

if(true){class A{}}
DECLARE_INHERITED_CLASS when declare a class by name,if declared class extends other class,will execute this opcode. JMPZ true JX
DECLARE_INHERITED_CLASS "a" "C" @0

if(true){
class a extends C{}
}
DECLARE_FUNCTION declare function by name JMPZ true JX
DECLARE_FUNCTION "test"

if(true){
function test(){}
}
RAISE_ABSTRACT_ERROR
DECLARE_CONST declare a const value DECLARE_CONST "a" 1
const a=1;
ADD_INTERFACE when declare class by name,if declared class implements other interface,will execute this opcode. JMPZ true JX
DECLARE_CLASS "a" @0
ADD_INTERFACE @0 "C"
VERIFY_ABSTRACT_CLASS @0

if(true){
class a implements C{}
}
DECLARE_INHERITED_CLASS_DELAYED
VERIFY_ABSTRACT_CLASS Could see ADD_INTERFACE part.
ASSIGN_DIM set value of variable by index,followed by OP_DATA. ASSIGN_DIM $x 0
OP_DATA 2

$x[0]=2;
OP_DATA set value after "ASSIGN" opcodes(such as ASSIGN_DIM,ASSIGN_OBJ...) executed. Could see ASSIGN_DIM part.
ISSET_ISEMPTY_PROP_OBJ check wether a property value of an object is setted and store the result ISSET_ISEMPTY_PROP_OBJ $a "b" ~0
isset($a->b);
HANDLE_EXCEPTION
USER_OPCODE
ZEND_ASSERT_CHECK
JMP_SET set the variable if value is not zero,otherwise jump to address JMP_SET $b JX ~0
QM_ASSIGN 2 ~0
ASSIGN $t ~0

$t=$b?:2;
DECLARE_LAMBDA_FUNCTION DECLARE_LAMBDA_FUNCTION "\000{clousre}C:\\"+ ~0
INIT_DYNAMIC_CALL ~0
DO_FCALL

(function(){return "phpinfo";})();
ADD_TRAIT followed by BIND_TRAITS DECLARE_CLASS "a" @0
ADD_TRAIT @0 "B"
BIND_TRAITS @0

class A{
use B;
}
BIND_TRAITS bind trait in class. Could see ADD_TRAIT part.
ZEND_SEPARATE
ZEND_FETCH_CLASS_NAME
ZEND_CALL_TRAMPOLINE
ZEND_DISCARD_EXCEPTION
ZEND_YIELD
ZEND_GENERATOR_RETURN
ZEND_FAST_CALL
ZEND_FAST_RET
ZEND_RECV_VARIADIC
ZEND_SEND_UNPACK
ZEND_POW
ZEND_ASSIGN_POW
ZEND_BIND_GLOBAL(vld)
BIND_GLOBAL
declare an global variable BIND_GLOBAL $a "a"
global $a;
ZEND_COALESCE
ZEND_SPACESHIP
ZEND_DECLARE_ANON_CLASS
ZEND_DECLARE_ANON_INHERITED_CLASS
ZEND_FETCH_STATIC_PROP_R
ZEND_FETCH_STATIC_PROP_W
ZEND_FETCH_STATIC_PROP_RW
ZEND_FETCH_STATIC_PROP_IS
ZEND_FETCH_STATIC_PROP_FUNC_ARG
ZEND_FETCH_STATIC_PROP_UNSET
ZEND_UNSET_STATIC_PROP
ZEND_ISSET_ISEMPTY_STATIC_PROP
ZEND_FETCH_CLASS_CONSTANT
ZEND_BIND_LEXICAL
ZEND_BIND_STATIC
ZEND_FETCH_THIS
ZEND_SEND_FUNC_ARG
ZEND_ISSET_ISEMPTY_THIS
ZEND_SWITCH_LONG
ZEND_SWITCH_STRING
ZEND_IN_ARRAY
ZEND_COUNT
ZEND_GET_CLASS
ZEND_GET_CALLED_CLASS
ZEND_GET_TYPE
ZEND_FUNC_NUM_ARGS
ZEND_FUNC_GET_ARGS
ZEND_UNSET_CV