php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #77561 Shebang line not stripped for non-primary script
Submitted: 2019-02-03 17:46 UTC Modified: 2020-08-10 08:36 UTC
Votes:5
Avg. Score:4.2 ± 0.7
Reproduced:4 of 4 (100.0%)
Same Version:3 (75.0%)
Same OS:3 (75.0%)
From: sebastian@php.net Assigned:
Status: Closed Package: Scripting Engine problem
PHP Version: 7.3.1 OS: Irrelevant
Private report: No CVE-ID: None
 [2019-02-03 17:46 UTC] sebastian@php.net
Description:
------------
It seems that there is a bug in PHP that when a PHAR is include()d or require()d and the PHAR's bootstrap script has a shebang such as "#!/usr/bin/env php" on its first line followed by "<?php declare(strict_types=1);" on its second line then PHP wrongly triggers a "strict_types declaration must be the very first statement in the script" compiler error.

See https://github.com/sebastianbergmann/phpunit/issues/3509 for an issue that showcases this problem in the context of PHPUnit's phpunit.phar.

I discussed this with Nikita who said "The strict_types error is correct, because the shebang line is interpreted as literal output (and will be printed to stdout unless you intercept that somehow). Shebangs are only stripped from the primary script if run via CLI. It would probably make sense to always strip them instead. This can probably only be fixed in 7.4 at the earliest, as it's a BC breaking change. Unless there is some phar-specific interaction here where it already strips the shebang but not for the purpose of strict_types handling)."


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2019-02-03 17:50 UTC] spam2 at rhsoft dot net
nobody cares, i worte a bugreport long ago that it don't matter if it's an include or a script called by mod_php or a BOM - the first php statement is after <?php and the special handling for pure shell scripts with shebang is crap

"very first statement in the script"
not BOM nor shebang are script statements
 [2019-02-03 18:30 UTC] cmb@php.net
> the first php statement is after <?php

See <https://3v4l.org/m0YBG/vld#output>.
 [2019-02-03 18:34 UTC] spam2 at rhsoft dot net
@cmb seriously?

the topic is about <?php declare(strict_types=1); and you come up with a simple missing the point?


[harry@srv-rhsoft:/downloads]$ cat test.php
foo
<?php declare(strict_types=1);
echo 'bar';

[harry@srv-rhsoft:/downloads]$ php test.php
Fatal error: strict_types declaration must be the very first statement in the script in /mnt/data/downloads/test.php on line 2
[harry@srv-rhsoft:/downloads]$
 [2019-02-03 19:24 UTC] phpbugs at olemartin dot org
I agree with @cmb that the example with arbitrary content before the start tag should produce the error. However, it's quite a gotcha that a shebang is stripped in some cases (when executed by the cli) but not others (when included). Same should go with a BOM (and other magic numbers?).

Since there are partial support for shebangs, that support should be made consistent.
 [2019-02-04 00:02 UTC] cmb@php.net
> the topic is about <?php declare(strict_types=1); and you come up with a simple missing the point?

My point is that PHP sees the whole file as a single script, and that everything outside of <?php ?> is simply “rewritten” to be echoed.  E.g.

    #!/usr/bin/env php
    <?php declare(strict_types=1);

is compiled the same as

    <?php
    echo "#!/usr/bin/env php\n";
    declare(strict_types=1);

So, declare is *not* the “very first statement in the script”.
 [2019-02-04 00:20 UTC] spam2 at rhsoft dot net
but for cli scripts exists an inconsistent hack für shebangs and the way it works makes it as example imposible write a strict-typed script which works with different SAPI's
 [2019-02-05 16:10 UTC] nikic@php.net
I just looked into this a bit. Shebang lines are currently handled by the SAPI layer, by stripping it off before it even reaches the lexer. The CLI SAPI always does this, while the CGI SAPI has a default-enabled ini option for it (cgi.check_shebang_line), that I learned about today. Other SAPIs don't have this option.

I think we'll want to move the shebang stripping into the lexer, but I'm not sure if we can get away with unconditionally enabling it.
 [2019-02-05 16:28 UTC] spam2 at rhsoft dot net
yeah that would solve this problem, in the example below 'auth.php' is a NOOP in case PHP_SAPI === 'cli' and when called from the webserver it verifies the userlogin and stops with a loginform

that's in fact a cronjob file and the web-call is for "i need that damned task now and not in 5 minutes" and i have dozens of examples where this makes sense

#!/usr/bin/php
<?php declare(strict_types=1);
require __DIR__ . '/../../auth.php';
$cl_api->worker->import();
?>
 [2019-07-15 14:46 UTC] nikic@php.net
Based on https://github.com/php/php-src/commit/c5f1b384b591009310370f0b06b10868d2d62741 it would now be (technically) easy to always strip shebang lines, though I'm not sure whether we should do actually do it.
 [2020-08-10 08:36 UTC] nikic@php.net
-Summary: PHAR bootstrap script with shebang and strict types does not work +Summary: Shebang line not stripped for non-primary script -Package: PHAR related +Package: Scripting Engine problem
 [2020-08-10 08:36 UTC] nikic@php.net
I'm going to enable unconditional stripping of the shebang line for the CLI SAPI in PHP 8.0. I think there is very little chance that someone intentionally want to preserve a shebang line when including a PHP file that starts with one, and this does regularly cause issues when scripts are reused in multiple contexts.
 [2020-08-10 08:40 UTC] nikic@php.net
Automatic comment on behalf of nikita.ppv@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=896dad4c794f7826812bcfdbaaa9f0b3518d9385
Log: Fixed bug #77561
 [2020-08-10 08:40 UTC] nikic@php.net
-Status: Open +Status: Closed
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 12:01:31 2024 UTC