Bug #78066 [Com]: PHP eats the first byte of a program that comes from process substitution

From: Date: Sat, 25 May 2019 20:07:32 +0000
Subject: Bug #78066 [Com]: PHP eats the first byte of a program that comes from process substitution
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-220990@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=78066&edit=1 ID: 78066 Comment by: xatenev@php.net Reported by: octalbugsphp at alvarezp dot org Summary: PHP eats the first byte of a program that comes from process substitution Status: Open Type: Bug Package: *General Issues Operating System: Linux PHP Version: 7.3.5 Block user comment: N Private report: N New Comment: ... Call the above snippet as specified in the bug report: gcc test.c ./a.out <(echo '<?php print("hello"); ?>') ----------------------------- Output: ?php print("hello"); ?> Previous Comments: ------------------------------------------------------------------------ [2019-05-25 20:03:45] xatenev@php.net Hi, I was able to reproduce the problem with a small test C snippet that mimics what php-src is doing: ------------------------------------- #include <stdio.h> #include <stdlib.h> int main(int argc, char* argv[]) { FILE *fp; fp = fopen(argv[1], "rb"); char a = fgetc(fp); rewind(fp); char ch; while(1) { ch = fgetc(fp); if(feof(fp)) { break; } printf("%c", ch); } return 0; } ------------------------------------- rewind() fills errno with the value 29 which means Illegal seek. The lines char a = fgetc(fp); rewind(fp); mimic what php-src is doing here on line 606 and 620: https://github.com/php/php-src/blob/e6f86fb17cd3a2dfe94ca1a0113a23194cb1915a/sapi/cli/php_cli.c#L606-L620 It calls fgetc() to find out if shebang exists on the file pointer but rewind() doesn't work correctly. ------------------------------------------------------------------------ [2019-05-25 16:53:55] simon at ikanobori dot jp Being part of that discussion, it is important to note that process substitution returns the path to an anonymous pipe which stops existing after the process finishes. ------------------------------------------------------------------------ [2019-05-25 16:52:01] octalbugsphp at alvarezp dot org Description: ------------ PHP eats the first byte of a program that comes from process substitution After discussion in ##php at Freenode this was found (see the third line, lseek) $ strace php -f <(echo -- '<?php print("hello\n"); ?>') 2>&1 | grep -A 5 'openat.*/dev/fd/63' openat(AT_FDCWD, "/dev/fd/63", O_RDONLY) = 3 fstat(3, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0 read(3, "-- <?php print(\"hello\\n\"); ?>\n", 4096) = 30 lseek(3, 0, SEEK_SET) = -1 ESPIPE (Illegal seek) lstat("/dev/fd/63", {st_mode=S_IFLNK|0500, st_size=64, ...}) = 0 readlink("/dev/fd/63", "pipe:[6195898]", 4096) = 14 Test script: --------------- [ 0][Sat May 25 11:05:07 -0500 -- alvarezp@alvarezp-samsung:~] $ php -f <(echo '<?php print("hello\n"); ?>') ?php print("hello\n"); ?> [ 0][Sat May 25 11:05:11 -0500 -- alvarezp@alvarezp-samsung:~] $ php -f <(echo ' <?php print("hello\n"); ?>') hello [ 0][Sat May 25 11:05:19 -0500 -- alvarezp@alvarezp-samsung:~] $ php -f <(echo -- '<?php print("hello\n"); ?>') - hello Expected result: ---------------- The script should run as expected. The first byte should prevail as part of the script. Actual result: -------------- The first byte is eaten and not interpreted at all. ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=78066&edit=1

« previous php.bugs (#220990) next »