@@ -731,11 +731,13 @@ overflow: ZEND_ATTRIBUTE_COLD_LABEL
731731 * have read the values of op1 and op2.
732732 */
733733
734+ zend_long sum = (zend_long ) ((zend_ulong ) Z_LVAL_P (op1 ) + (zend_ulong ) Z_LVAL_P (op2 ));
735+
734736 if (UNEXPECTED ((Z_LVAL_P (op1 ) & LONG_SIGN_MASK ) == (Z_LVAL_P (op2 ) & LONG_SIGN_MASK )
735- && (Z_LVAL_P (op1 ) & LONG_SIGN_MASK ) != (( Z_LVAL_P ( op1 ) + Z_LVAL_P ( op2 )) & LONG_SIGN_MASK ))) {
737+ && (Z_LVAL_P (op1 ) & LONG_SIGN_MASK ) != (sum & LONG_SIGN_MASK ))) {
736738 ZVAL_DOUBLE (result , (double ) Z_LVAL_P (op1 ) + (double ) Z_LVAL_P (op2 ));
737739 } else {
738- ZVAL_LONG (result , Z_LVAL_P ( op1 ) + Z_LVAL_P ( op2 ) );
740+ ZVAL_LONG (result , sum );
739741 }
740742#endif
741743}
@@ -813,11 +815,19 @@ overflow: ZEND_ATTRIBUTE_COLD_LABEL
813815 ZVAL_LONG (result , llresult );
814816 }
815817#else
816- ZVAL_LONG (result , Z_LVAL_P (op1 ) - Z_LVAL_P (op2 ));
818+ /*
819+ * 'result' may alias with op1 or op2, so we need to
820+ * ensure that 'result' is not updated until after we
821+ * have read the values of op1 and op2.
822+ */
823+
824+ zend_long sub = (zend_long ) ((zend_ulong ) Z_LVAL_P (op1 ) - (zend_ulong ) Z_LVAL_P (op2 ));
817825
818826 if (UNEXPECTED ((Z_LVAL_P (op1 ) & LONG_SIGN_MASK ) != (Z_LVAL_P (op2 ) & LONG_SIGN_MASK )
819- && (Z_LVAL_P (op1 ) & LONG_SIGN_MASK ) != (Z_LVAL_P ( result ) & LONG_SIGN_MASK ))) {
827+ && (Z_LVAL_P (op1 ) & LONG_SIGN_MASK ) != (sub & LONG_SIGN_MASK ))) {
820828 ZVAL_DOUBLE (result , (double ) Z_LVAL_P (op1 ) - (double ) Z_LVAL_P (op2 ));
829+ } else {
830+ ZVAL_LONG (result , sub );
821831 }
822832#endif
823833}
0 commit comments