php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #78489 "php -a" will terminate immediately for any thrown CompileError
Submitted: 2019-09-04 01:40 UTC Modified: -
From: tandre@php.net Assigned:
Status: Open Package: *General Issues
PHP Version: 7.3.9 OS:
Private report: No CVE-ID: None
 [2019-09-04 01:40 UTC] tandre@php.net
Description:
------------
Observed: "php -a" terminates immediately when CompileError is thrown and not caught, but does not terminate for any thrown subclass (e.g. ParseError)
Expected: "php -a" should report the error appropriately, but not terminate 
Cause: https://github.com/php/php-src/pull/2767#discussion_r320539776

// in main/main.c, we see that E_COMPILE_ERROR is treated differently from E_PARSE, and zend_ce_compile_error causes E_COMPILE_ERROR.
// Changing main.c to check if E_COMPILE_ERROR is recoverable would fix the bug.
			case E_ERROR:
			case E_CORE_ERROR:
			case E_COMPILE_ERROR:
			case E_USER_ERROR:
				error_type_str = "Fatal error";
				syslog_type_int = LOG_ERR;
				break;

Test script:
---------------
php > throw new ParseError('x');
Parse error: x in php shell code on line 1
php > throw new CompileError('x');
Fatal error: x in php shell code on line 1
.... This terminates php -a
php > var_export(token_get_all('<?php abstract final class X{}', TOKEN_PARSE));
Fatal error: Cannot use the final modifier on an abstract class in  on line 1
.... This also terminates php -a
php > try {throw new CompileError('x');} catch (Throwable $_) { var_export($_); }
Outputs CompileError::__set_state(array(...

Expected result:
----------------
"php -a" should report the error appropriately, but not terminate 

Actual result:
--------------
Observed: "php -a" terminates immediately when CompileError is thrown and not caught, but does not terminate for any thrown subclass (e.g. ParseError)


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2019-09-04 01:48 UTC] tandre@php.net
Just noticed on https://github.com/php/php-src/pull/2767#issue-142753913

> Additionally reusing the ParseError class for this purpose would change existing error messages (if the exception is not caught) from a "Fatal error:" to a "Parse error:" prefix, and also the error kind from E_COMPILE_ERROR to E_PARSE.

Keeping "Fatal error" (or making it "Recoverable fatal error" if in a different file?) might make sense for SAPIs other than the one used for "php -a".

This block of `php_error_cb` looks like the reason why php -a bails out unless the error type is E_PARSE (not E_COMPILE_ERROR)

				/* the parser would return 1 (failure), we can bail out nicely */
				if (type != E_PARSE) {
					/* restore memory limit */
					zend_set_memory_limit(PG(memory_limit));
					efree(buffer);
					zend_objects_store_mark_destructed(&EG(objects_store));
					zend_bailout();
					return;
				}
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Mon Dec 09 07:01:27 2024 UTC