php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #77561 PHAR bootstrap script with shebang and strict types does not work
Submitted: 2019-02-03 17:46 UTC Modified: 2019-07-15 14:46 UTC
Votes:4
Avg. Score:4.2 ± 0.8
Reproduced:3 of 3 (100.0%)
Same Version:2 (66.7%)
Same OS:2 (66.7%)
From: sebastian@php.net Assigned:
Status: Open Package: PHAR related
PHP Version: 7.3.1 OS: Irrelevant
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [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

Add a Patch

Pull Requests

Add a Pull Request

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.
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Sun Aug 18 18:01:27 2019 UTC