summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS2
-rw-r--r--Zend/tests/bug69957.phpt80
-rw-r--r--Zend/zend_compile.c2
-rw-r--r--Zend/zend_operators.c54
-rw-r--r--Zend/zend_vm_def.h2
-rw-r--r--Zend/zend_vm_execute.h18
6 files changed, 126 insertions, 32 deletions
diff --git a/NEWS b/NEWS
index 4f5de4e88f..b073ec3f9d 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,8 @@ PHP NEWS
- Core:
. Fixed bug #69768 (escapeshell*() doesn't cater to !). (cmb)
+ . Fixed bug #69957 (Three different ways of handling same error condition).
+ (Bob)
- CLI server:
. Fixed bug #69655 (php -S changes MKCALENDAR request method to MKCOL). (cmb)
diff --git a/Zend/tests/bug69957.phpt b/Zend/tests/bug69957.phpt
new file mode 100644
index 0000000000..d6f441b6ea
--- /dev/null
+++ b/Zend/tests/bug69957.phpt
@@ -0,0 +1,80 @@
+--TEST--
+Bug #69957 (Different ways of handling div/mod by zero)
+--FILE--
+<?php
+
+try {
+ $divisor = 0;
+ $result = 1 / $divisor;
+} catch (Throwable $t){
+ echo "Variable div\n";
+ printf("Type: %s\n", get_class($t));
+ printf("Message: %s\n", $t->getMessage());
+}
+
+try {
+ $divisor = 0;
+ $result = 1 % $divisor;
+} catch (Throwable $t){
+ echo "\nVariable mod\n";
+ printf("Type: %s\n", get_class($t));
+ printf("Message: %s\n", $t->getMessage());
+}
+
+try {
+ $result = 1 / 0;
+} catch (Throwable $t){
+ echo "\nLiteral div\n";
+ printf("Type: %s\n", get_class($t));
+ printf("Message: %s\n", $t->getMessage());
+}
+
+try {
+ $result = 1 % 0;
+} catch (Throwable $t){
+ echo "\nLiteral mod\n";
+ printf("Type: %s\n", get_class($t));
+ printf("Message: %s\n", $t->getMessage());
+}
+
+try {
+ $result = 1 / 0.0;
+} catch (Throwable $t){
+ echo "\nDouble div\n";
+ printf("Type: %s\n", get_class($t));
+ printf("Message: %s\n", $t->getMessage());
+}
+
+try {
+ $result = 1 % 0.0;
+} catch (Throwable $t){
+ echo "\nDouble mod\n";
+ printf("Type: %s\n", get_class($t));
+ printf("Message: %s\n", $t->getMessage());
+}
+
+?>
+--EXPECT--
+Variable div
+Type: Error
+Message: Division by zero
+
+Variable mod
+Type: Error
+Message: Modulo by zero
+
+Literal div
+Type: Error
+Message: Division by zero
+
+Literal mod
+Type: Error
+Message: Modulo by zero
+
+Double div
+Type: Error
+Message: Division by zero
+
+Double mod
+Type: Error
+Message: Modulo by zero
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 2e0822fdd4..7194aacdb5 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -5625,7 +5625,7 @@ static inline zend_bool zend_try_ct_eval_binary_op(zval *result, uint32_t opcode
binary_op_type fn = get_binary_op(opcode);
/* don't evaluate division by zero at compile-time */
- if (opcode == ZEND_DIV) {
+ if (opcode == ZEND_DIV || opcode == ZEND_MOD) {
convert_scalar_to_number(op2);
if (Z_TYPE_P(op2) == IS_LONG) {
if (Z_LVAL_P(op2) == 0) {
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index d9670a5a49..9439296657 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -1103,16 +1103,19 @@ ZEND_API int ZEND_FASTCALL div_function(zval *result, zval *op1, zval *op2) /* {
while (1) {
switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
case TYPE_PAIR(IS_LONG, IS_LONG):
- if (Z_LVAL_P(op2) == 0) {
- zend_error(E_WARNING, "Division by zero");
+ if (UNEXPECTED(Z_LVAL_P(op2) == 0)) {
+ if (EG(current_execute_data) && !CG(in_compilation)) {
+ zend_error(E_ERROR | E_EXCEPTION, "Division by zero");
+ } else {
+ zend_error_noreturn(E_ERROR, "Division by zero");
+ }
ZVAL_DOUBLE(result, ((double) Z_LVAL_P(op1) / (double) Z_LVAL_P(op2)));
return SUCCESS;
- } else if (Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == ZEND_LONG_MIN) {
+ } else if (UNEXPECTED(Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == ZEND_LONG_MIN)) {
/* Prevent overflow error/crash */
ZVAL_DOUBLE(result, (double) ZEND_LONG_MIN / -1);
return SUCCESS;
- }
- if (Z_LVAL_P(op1) % Z_LVAL_P(op2) == 0) { /* integer */
+ } else if (Z_LVAL_P(op1) % Z_LVAL_P(op2) == 0) { /* integer */
ZVAL_LONG(result, Z_LVAL_P(op1) / Z_LVAL_P(op2));
} else {
ZVAL_DOUBLE(result, ((double) Z_LVAL_P(op1)) / Z_LVAL_P(op2));
@@ -1120,22 +1123,34 @@ ZEND_API int ZEND_FASTCALL div_function(zval *result, zval *op1, zval *op2) /* {
return SUCCESS;
case TYPE_PAIR(IS_DOUBLE, IS_LONG):
- if (Z_LVAL_P(op2) == 0) {
- zend_error(E_WARNING, "Division by zero");
+ if (UNEXPECTED(Z_LVAL_P(op2) == 0)) {
+ if (EG(current_execute_data) && !CG(in_compilation)) {
+ zend_error(E_ERROR | E_EXCEPTION, "Division by zero");
+ } else {
+ zend_error_noreturn(E_ERROR, "Division by zero");
+ }
}
ZVAL_DOUBLE(result, Z_DVAL_P(op1) / (double)Z_LVAL_P(op2));
return SUCCESS;
case TYPE_PAIR(IS_LONG, IS_DOUBLE):
- if (Z_DVAL_P(op2) == 0) {
- zend_error(E_WARNING, "Division by zero");
+ if (UNEXPECTED(Z_DVAL_P(op2) == 0)) {
+ if (EG(current_execute_data) && !CG(in_compilation)) {
+ zend_error(E_ERROR | E_EXCEPTION, "Division by zero");
+ } else {
+ zend_error_noreturn(E_ERROR, "Division by zero");
+ }
}
ZVAL_DOUBLE(result, (double)Z_LVAL_P(op1) / Z_DVAL_P(op2));
return SUCCESS;
case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
- if (Z_DVAL_P(op2) == 0) {
- zend_error(E_WARNING, "Division by zero");
+ if (UNEXPECTED(Z_DVAL_P(op2) == 0)) {
+ if (EG(current_execute_data) && !CG(in_compilation)) {
+ zend_error(E_ERROR | E_EXCEPTION, "Division by zero");
+ } else {
+ zend_error_noreturn(E_ERROR, "Division by zero");
+ }
}
ZVAL_DOUBLE(result, Z_DVAL_P(op1) / Z_DVAL_P(op2));
return SUCCESS;
@@ -1170,24 +1185,21 @@ ZEND_API int ZEND_FASTCALL mod_function(zval *result, zval *op1, zval *op2) /* {
zval_dtor(result);
}
- if (op2_lval == 0) {
+ if (UNEXPECTED(op2_lval == 0)) {
/* modulus by zero */
if (EG(current_execute_data) && !CG(in_compilation)) {
- zend_throw_exception_ex(NULL, 0, "Division by zero");
+ zend_error(E_ERROR | E_EXCEPTION, "Modulo by zero");
} else {
- zend_error_noreturn(E_ERROR, "Division by zero");
+ zend_error_noreturn(E_ERROR, "Modulo by zero");
}
ZVAL_UNDEF(result);
return FAILURE;
- }
-
- if (op2_lval == -1) {
- /* Prevent overflow error/crash if op1==LONG_MIN */
+ } else if (UNEXPECTED(op2_lval == -1)) {
+ /* Prevent overflow error/crash if op1 == LONG_MIN */
ZVAL_LONG(result, 0);
- return SUCCESS;
+ } else {
+ ZVAL_LONG(result, op1_lval % op2_lval);
}
-
- ZVAL_LONG(result, op1_lval % op2_lval);
return SUCCESS;
}
/* }}} */
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 933be83dc7..1d18d4be06 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -189,7 +189,7 @@ ZEND_VM_HANDLER(5, ZEND_MOD, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
result = EX_VAR(opline->result.var);
if (UNEXPECTED(Z_LVAL_P(op2) == 0)) {
SAVE_OPLINE();
- zend_throw_exception_ex(NULL, 0, "Division by zero");
+ zend_error(E_ERROR | E_EXCEPTION, "Modulo by zero");
HANDLE_EXCEPTION();
} else if (UNEXPECTED(Z_LVAL_P(op2) == -1)) {
/* Prevent overflow error/crash if op1==ZEND_LONG_MIN */
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 133a1d11a4..ffe55d9a62 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -4490,7 +4490,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_CONST_CONST_HANDLER(Z
result = EX_VAR(opline->result.var);
if (UNEXPECTED(Z_LVAL_P(op2) == 0)) {
SAVE_OPLINE();
- zend_throw_exception_ex(NULL, 0, "Division by zero");
+ zend_error(E_ERROR | E_EXCEPTION, "Modulo by zero");
HANDLE_EXCEPTION();
} else if (UNEXPECTED(Z_LVAL_P(op2) == -1)) {
/* Prevent overflow error/crash if op1==ZEND_LONG_MIN */
@@ -8513,7 +8513,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_CONST_CV_HANDLER(ZEND
result = EX_VAR(opline->result.var);
if (UNEXPECTED(Z_LVAL_P(op2) == 0)) {
SAVE_OPLINE();
- zend_throw_exception_ex(NULL, 0, "Division by zero");
+ zend_error(E_ERROR | E_EXCEPTION, "Modulo by zero");
HANDLE_EXCEPTION();
} else if (UNEXPECTED(Z_LVAL_P(op2) == -1)) {
/* Prevent overflow error/crash if op1==ZEND_LONG_MIN */
@@ -10388,7 +10388,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_CONST_TMPVAR_HANDLER(
result = EX_VAR(opline->result.var);
if (UNEXPECTED(Z_LVAL_P(op2) == 0)) {
SAVE_OPLINE();
- zend_throw_exception_ex(NULL, 0, "Division by zero");
+ zend_error(E_ERROR | E_EXCEPTION, "Modulo by zero");
HANDLE_EXCEPTION();
} else if (UNEXPECTED(Z_LVAL_P(op2) == -1)) {
/* Prevent overflow error/crash if op1==ZEND_LONG_MIN */
@@ -30202,7 +30202,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_CV_CONST_HANDLER(ZEND
result = EX_VAR(opline->result.var);
if (UNEXPECTED(Z_LVAL_P(op2) == 0)) {
SAVE_OPLINE();
- zend_throw_exception_ex(NULL, 0, "Division by zero");
+ zend_error(E_ERROR | E_EXCEPTION, "Modulo by zero");
HANDLE_EXCEPTION();
} else if (UNEXPECTED(Z_LVAL_P(op2) == -1)) {
/* Prevent overflow error/crash if op1==ZEND_LONG_MIN */
@@ -35514,7 +35514,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_CV_CV_HANDLER(ZEND_OP
result = EX_VAR(opline->result.var);
if (UNEXPECTED(Z_LVAL_P(op2) == 0)) {
SAVE_OPLINE();
- zend_throw_exception_ex(NULL, 0, "Division by zero");
+ zend_error(E_ERROR | E_EXCEPTION, "Modulo by zero");
HANDLE_EXCEPTION();
} else if (UNEXPECTED(Z_LVAL_P(op2) == -1)) {
/* Prevent overflow error/crash if op1==ZEND_LONG_MIN */
@@ -38247,7 +38247,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_CV_TMPVAR_HANDLER(ZEN
result = EX_VAR(opline->result.var);
if (UNEXPECTED(Z_LVAL_P(op2) == 0)) {
SAVE_OPLINE();
- zend_throw_exception_ex(NULL, 0, "Division by zero");
+ zend_error(E_ERROR | E_EXCEPTION, "Modulo by zero");
HANDLE_EXCEPTION();
} else if (UNEXPECTED(Z_LVAL_P(op2) == -1)) {
/* Prevent overflow error/crash if op1==ZEND_LONG_MIN */
@@ -41322,7 +41322,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_TMPVAR_CONST_HANDLER(
result = EX_VAR(opline->result.var);
if (UNEXPECTED(Z_LVAL_P(op2) == 0)) {
SAVE_OPLINE();
- zend_throw_exception_ex(NULL, 0, "Division by zero");
+ zend_error(E_ERROR | E_EXCEPTION, "Modulo by zero");
HANDLE_EXCEPTION();
} else if (UNEXPECTED(Z_LVAL_P(op2) == -1)) {
/* Prevent overflow error/crash if op1==ZEND_LONG_MIN */
@@ -43752,7 +43752,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_TMPVAR_CV_HANDLER(ZEN
result = EX_VAR(opline->result.var);
if (UNEXPECTED(Z_LVAL_P(op2) == 0)) {
SAVE_OPLINE();
- zend_throw_exception_ex(NULL, 0, "Division by zero");
+ zend_error(E_ERROR | E_EXCEPTION, "Modulo by zero");
HANDLE_EXCEPTION();
} else if (UNEXPECTED(Z_LVAL_P(op2) == -1)) {
/* Prevent overflow error/crash if op1==ZEND_LONG_MIN */
@@ -44915,7 +44915,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_TMPVAR_TMPVAR_HANDLER
result = EX_VAR(opline->result.var);
if (UNEXPECTED(Z_LVAL_P(op2) == 0)) {
SAVE_OPLINE();
- zend_throw_exception_ex(NULL, 0, "Division by zero");
+ zend_error(E_ERROR | E_EXCEPTION, "Modulo by zero");
HANDLE_EXCEPTION();
} else if (UNEXPECTED(Z_LVAL_P(op2) == -1)) {
/* Prevent overflow error/crash if op1==ZEND_LONG_MIN */