php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #69957 Three different ways of handling same error condition
Submitted: 2015-06-28 14:24 UTC Modified: 2015-07-04 23:00 UTC
Votes:1
Avg. Score:3.0 ± 0.0
Reproduced:0 of 0 (0.0%)
From: cameron dot adam+php at gmail dot com Assigned: bwoebi
Status: Closed Package: Scripting Engine problem
PHP Version: 7.0.0alpha2 OS: Windows 7 64-bit
Private report: No CVE-ID:
 [2015-06-28 14:24 UTC] cameron dot adam+php at gmail dot com
Description:
------------
I've included three files below (originals at https://github.com/adamcameron/php/tree/master/php.local/www/experiment/compilation/literal)

There are six runtime variations in all, testing divide-by-zero operations with each of / and then %.

There are three different error variations depending on the test.

There should be only one: a runtime DivisionByZeroException, or perhaps an ArithmeticException, or even just an ExpressionException or something. But only *one* treatment of all six variations.

See http://blog.adamcameron.me/2015/06/php-7-three-different-ways-of-dealing.html for equiv code run in CFML and Ruby demonstrating they do not share PHP's error-handling "vagaries" here. Apologies for uncharitable tone re PHP in that article, but I think it's mostly warranted.

Cheers.

Test script:
---------------
<?php
// literal.php
$operator = $_GET['operator'] ?? 'divide';
try {
	if ($operator == 'divide'){
		$result = 1 / 0;
	}else{
		$result = 1 % 0;
	}
} catch (Throwable $t){
	echo "Operator: $operator<br>";
	printf("Type: %s<br>", get_class($t));
	printf("Message: %s<br>", $t->getMessage());
}

<?php
// literalViaVariable.php
$operator = $_GET['operator'] ?? 'divide';
$divisor = 0;
try {
	if ($operator == 'divide'){
		$result = 1 / $divisor;
	}else{
		$result = 1 % $divisor;
	}
} catch (Throwable $t){
	echo "Operator: $operator<br>";
	printf("Type: %s<br>", get_class($t));
	printf("Message: %s<br>", $t->getMessage());
}

<?php
// viaParam.php
$operator = $_GET['operator'] ?? 'divide';
$divisor = $_GET['divisor'] ?? 1;
try {
	if ($operator == 'divide'){
		$result = 1 / $divisor;
	}else{
		$result = 1 % $divisor;
	}
} catch (Throwable $t){
	echo "Operator: $operator<br>";
	printf("Type: %s<br>", get_class($t));
	printf("Message: %s<br>", $t->getMessage());
}

Expected result:
----------------
The same catchable runtime exception to be thrown for all six possible variations of the three code examples above.

Actual result:
--------------
1) Fatal error in the literal.php example
2) Warning when using / operator in runtime divide by zero situations
3) Throwable when using % operator in runtime divide by zero situations

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-06-28 16:07 UTC] bwoebi@php.net
-Status: Open +Status: Assigned -Assigned To: +Assigned To: bwoebi
 [2015-06-28 16:07 UTC] bwoebi@php.net
Okay, I see we should normalize div and mod… ;-)
 [2015-06-28 16:23 UTC] bwoebi@php.net
Automatic comment on behalf of bobwei9@hotmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=fb08798c9f0ea820d567668d0cea4833dc61dd8e
Log: Fix bug #69957 (Different ways of handling div/mod by zero)
 [2015-06-28 16:23 UTC] bwoebi@php.net
-Status: Assigned +Status: Closed
 [2015-06-28 16:25 UTC] bwoebi@php.net
Note that it now all is an Error. We may eventually change it to a more specific error, but Error is good enough for the moment, I think.

See http://git.php.net/?p=php-src.git;a=blob;f=Zend/tests/bug69957.phpt;h=d6f441b6ea93ae50607ddbeb118aca32361691f3;hb=fb08798c9f0ea820d567668d0cea4833dc61dd8e for current behavior.
 [2015-06-28 16:41 UTC] cameron dot adam+php at gmail dot com
OK, just to be clear... a *catchable* error, yes?

Thanks for jumping on this so quickly, btw :-)

-- 
Adam
 [2015-06-28 17:22 UTC] bwoebi@php.net
yes, the Error class which extends Throwable. … All catchable ;-)
 [2015-06-29 09:18 UTC] ab@php.net
-Status: Closed +Status: Re-Opened
 [2015-06-29 09:18 UTC] ab@php.net
Hi Bob,

this breaks the discussed behaviors and should be reverted. See the intdiv RFC and http://www.serverphorums.com/read.php?7,1174854 . I guess to fix this the correct behavior needs to be discussed and defined.

Thanks.
 [2015-06-29 10:24 UTC] dmitry@php.net
The patch was reverted.
Division by zero doesn't throw exception on purpose.
It emits warning and returns INF.
 [2015-06-29 10:32 UTC] cameron dot adam+php at gmail dot com
Yeah, got that. My point was not that your not fulfilling the prescribed behaviour, it's that the behaviour you're prescribing lacks uniformity, and - in the bigger scheme of things - isn't terribly sensible or helpful.

The article I link to in the original ticket details this: I did not want to duplicate it here for various reasons.

Cheers.
 [2015-06-29 13:26 UTC] bwoebi@php.net
Hmm, okay.

I noticed that mod_function didn't throw in 5.6. I though the division was accidentally missed out.

Sorry for the bad communication; I totally didn't recall that it was discussed before.
 [2015-07-02 19:21 UTC] bwoebi@php.net
-Status: Re-Opened +Status: Closed
 [2015-07-02 19:21 UTC] bwoebi@php.net
Okay, now fixed for real via

http://git.php.net/?p=php-src.git;a=commitdiff;h=f9724b93f6592d2f77fa9165038a0ba0db3da0c6
http://git.php.net/?p=php-src.git;a=commitdiff;h=007d7ac7ca6d52ba5e7a0ba7b2c582a04ddc50df
http://git.php.net/?p=php-src.git;a=commitdiff;h=94722e12cf4ba9a16f8a9f009d60b2e3f0f80e12

Warning was removed completely for division by zero.
DivisionByZeroError extends ArtithmeticError extends Error introduced for mod and intdiv.
 [2015-07-04 23:00 UTC] googleguy@php.net
-Status: Closed +Status: Re-Opened
 [2015-07-04 23:00 UTC] googleguy@php.net
This issue has been reopen due to ongoing discussion in the mailing list (see http://news.php.net/php.internals/87016)

How you chose to handle a division by zero error in your code (in floating point arithmetic) shouldn't be dictated by whether or not PHP throws an exception, since exception handling is not the only way to handle errors in a program, nor is this exceptional in PHP since with a/0 returning INF per IEE754, we have well defined behavior.

However, removing the warning removes useful error information the programmer could otherwise use to debug potentially buggy code. So the E_WARNING should be brought back and all other behavior remain the same.
 [2015-07-07 23:37 UTC] ab@php.net
Automatic comment on behalf of bobwei9@hotmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=fb08798c9f0ea820d567668d0cea4833dc61dd8e
Log: Fix bug #69957 (Different ways of handling div/mod by zero)
 [2015-07-07 23:37 UTC] ab@php.net
-Status: Re-Opened +Status: Closed
 [2016-07-20 11:38 UTC] davey@php.net
Automatic comment on behalf of bobwei9@hotmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=fb08798c9f0ea820d567668d0cea4833dc61dd8e
Log: Fix bug #69957 (Different ways of handling div/mod by zero)
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Wed Mar 29 17:01:58 2017 UTC