From: Nikita Popov Date: Wed, 19 Jun 2019 10:59:18 +0000 (+0200) Subject: Fix signed shift UB X-Git-Tag: php-7.4.0alpha2~51^2~20 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ed2a242317213e7f483b2967c2921d2bae5d1097;p=php Fix signed shift UB --- diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 384884965d..14019a5afa 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -1757,7 +1757,8 @@ ZEND_API int ZEND_FASTCALL shift_left_function(zval *result, zval *op1, zval *op zval_ptr_dtor(result); } - ZVAL_LONG(result, op1_lval << op2_lval); + /* Perform shift on unsigned numbers to get well-defined wrap behavior. */ + ZVAL_LONG(result, (zend_long) ((zend_ulong) op1_lval << op2_lval)); return SUCCESS; } /* }}} */ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 2cb9d038a4..ab0a6fbd1c 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -227,7 +227,9 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(6, ZEND_SL, CONST|TMPVAR|CV, CONST|TMPVAR|CV) if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG) && EXPECTED((zend_ulong)Z_LVAL_P(op2) < SIZEOF_ZEND_LONG * 8)) { - ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) << Z_LVAL_P(op2)); + /* Perform shift on unsigned numbers to get well-defined wrap behavior. */ + ZVAL_LONG(EX_VAR(opline->result.var), + (zend_long) ((zend_ulong) Z_LVAL_P(op1) << Z_LVAL_P(op2))); ZEND_VM_NEXT_OPCODE(); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index e6d8e88473..7b535d62bf 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4507,7 +4507,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_CONST_CON if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG) && EXPECTED((zend_ulong)Z_LVAL_P(op2) < SIZEOF_ZEND_LONG * 8)) { - ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) << Z_LVAL_P(op2)); + /* Perform shift on unsigned numbers to get well-defined wrap behavior. */ + ZVAL_LONG(EX_VAR(opline->result.var), + (zend_long) ((zend_ulong) Z_LVAL_P(op1) << Z_LVAL_P(op2))); ZEND_VM_NEXT_OPCODE(); } @@ -6821,7 +6823,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_CONST_TMPVAR_HANDLER(Z if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG) && EXPECTED((zend_ulong)Z_LVAL_P(op2) < SIZEOF_ZEND_LONG * 8)) { - ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) << Z_LVAL_P(op2)); + /* Perform shift on unsigned numbers to get well-defined wrap behavior. */ + ZVAL_LONG(EX_VAR(opline->result.var), + (zend_long) ((zend_ulong) Z_LVAL_P(op1) << Z_LVAL_P(op2))); ZEND_VM_NEXT_OPCODE(); } @@ -9471,7 +9475,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_CONST_CV_HANDLER(ZEND_ if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG) && EXPECTED((zend_ulong)Z_LVAL_P(op2) < SIZEOF_ZEND_LONG * 8)) { - ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) << Z_LVAL_P(op2)); + /* Perform shift on unsigned numbers to get well-defined wrap behavior. */ + ZVAL_LONG(EX_VAR(opline->result.var), + (zend_long) ((zend_ulong) Z_LVAL_P(op1) << Z_LVAL_P(op2))); ZEND_VM_NEXT_OPCODE(); } @@ -12926,7 +12932,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_TMPVAR_CONST_HANDLER(Z if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG) && EXPECTED((zend_ulong)Z_LVAL_P(op2) < SIZEOF_ZEND_LONG * 8)) { - ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) << Z_LVAL_P(op2)); + /* Perform shift on unsigned numbers to get well-defined wrap behavior. */ + ZVAL_LONG(EX_VAR(opline->result.var), + (zend_long) ((zend_ulong) Z_LVAL_P(op1) << Z_LVAL_P(op2))); ZEND_VM_NEXT_OPCODE(); } @@ -14510,7 +14518,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_TMPVAR_TMPVAR_HANDLER( if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG) && EXPECTED((zend_ulong)Z_LVAL_P(op2) < SIZEOF_ZEND_LONG * 8)) { - ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) << Z_LVAL_P(op2)); + /* Perform shift on unsigned numbers to get well-defined wrap behavior. */ + ZVAL_LONG(EX_VAR(opline->result.var), + (zend_long) ((zend_ulong) Z_LVAL_P(op1) << Z_LVAL_P(op2))); ZEND_VM_NEXT_OPCODE(); } @@ -16214,7 +16224,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_TMPVAR_CV_HANDLER(ZEND if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG) && EXPECTED((zend_ulong)Z_LVAL_P(op2) < SIZEOF_ZEND_LONG * 8)) { - ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) << Z_LVAL_P(op2)); + /* Perform shift on unsigned numbers to get well-defined wrap behavior. */ + ZVAL_LONG(EX_VAR(opline->result.var), + (zend_long) ((zend_ulong) Z_LVAL_P(op1) << Z_LVAL_P(op2))); ZEND_VM_NEXT_OPCODE(); } @@ -38589,7 +38601,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_CV_CONST_HANDLER(ZEND_ if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG) && EXPECTED((zend_ulong)Z_LVAL_P(op2) < SIZEOF_ZEND_LONG * 8)) { - ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) << Z_LVAL_P(op2)); + /* Perform shift on unsigned numbers to get well-defined wrap behavior. */ + ZVAL_LONG(EX_VAR(opline->result.var), + (zend_long) ((zend_ulong) Z_LVAL_P(op1) << Z_LVAL_P(op2))); ZEND_VM_NEXT_OPCODE(); } @@ -42459,7 +42473,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_CV_TMPVAR_HANDLER(ZEND if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG) && EXPECTED((zend_ulong)Z_LVAL_P(op2) < SIZEOF_ZEND_LONG * 8)) { - ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) << Z_LVAL_P(op2)); + /* Perform shift on unsigned numbers to get well-defined wrap behavior. */ + ZVAL_LONG(EX_VAR(opline->result.var), + (zend_long) ((zend_ulong) Z_LVAL_P(op1) << Z_LVAL_P(op2))); ZEND_VM_NEXT_OPCODE(); } @@ -47894,7 +47910,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_CV_CV_HANDLER(ZEND_OPC if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG) && EXPECTED((zend_ulong)Z_LVAL_P(op2) < SIZEOF_ZEND_LONG * 8)) { - ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) << Z_LVAL_P(op2)); + /* Perform shift on unsigned numbers to get well-defined wrap behavior. */ + ZVAL_LONG(EX_VAR(opline->result.var), + (zend_long) ((zend_ulong) Z_LVAL_P(op1) << Z_LVAL_P(op2))); ZEND_VM_NEXT_OPCODE(); }