]> granicus.if.org Git - php/commitdiff
Fix signed shift UB
authorNikita Popov <nikita.ppv@gmail.com>
Wed, 19 Jun 2019 10:59:18 +0000 (12:59 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Wed, 19 Jun 2019 13:09:00 +0000 (15:09 +0200)
Zend/zend_operators.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index 384884965d759a7796817a4470b54fcdafea64e7..14019a5afa8feca3089f3a2959eeb2f7fc7c3d95 100644 (file)
@@ -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;
 }
 /* }}} */
index 2cb9d038a44a0f8619e5c83985c549aa4a87b400..ab0a6fbd1c96a5a8d195abc9591c4e88ee3cbf7b 100644 (file)
@@ -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();
        }
 
index e6d8e884738550a17abd40ef54d580cbdea53173..7b535d62bf88126cd71fa130623cfb61494e2008 100644 (file)
@@ -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();
        }