diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2020-08-05 11:27:13 +0200 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2020-08-06 10:26:46 +0200 |
commit | ab36540bddb63139c3da9a9da5e5feacdf7bf7bf (patch) | |
tree | 696a4fed7e6605f0df93986e4504818e00012abe | |
parent | 0dda242bde8f2d79437ab75cda5781f0a73cebcc (diff) | |
download | php-git-ab36540bddb63139c3da9a9da5e5feacdf7bf7bf.tar.gz |
Explicitly validate popen mode
To avoid behavior differences due to libc.
-rw-r--r-- | ext/standard/file.c | 8 | ||||
-rw-r--r-- | ext/standard/tests/file/popen_pclose_error.phpt | 2 |
2 files changed, 9 insertions, 1 deletions
diff --git a/ext/standard/file.c b/ext/standard/file.c index 98578376b0..88ffba8102 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -930,10 +930,18 @@ PHP_FUNCTION(popen) char *z = memchr(posix_mode, 'b', mode_len); if (z) { memmove(z, z + 1, mode_len - (z - posix_mode)); + mode_len--; } } #endif + /* Musl only partially validates the mode. Manually check it to ensure consistent behavior. */ + if (mode_len != 1 || (*posix_mode != 'r' && *posix_mode != 'w')) { + php_error_docref2(NULL, command, posix_mode, E_WARNING, "Invalid mode"); + efree(posix_mode); + RETURN_FALSE; + } + fp = VCWD_POPEN(command, posix_mode); if (!fp) { php_error_docref2(NULL, command, posix_mode, E_WARNING, "%s", strerror(errno)); diff --git a/ext/standard/tests/file/popen_pclose_error.phpt b/ext/standard/tests/file/popen_pclose_error.phpt index 2f05e7788d..0713280870 100644 --- a/ext/standard/tests/file/popen_pclose_error.phpt +++ b/ext/standard/tests/file/popen_pclose_error.phpt @@ -22,7 +22,7 @@ unlink($file_path."/popen.tmp"); --EXPECTF-- *** Testing for error conditions *** -Warning: popen(abc.txt,rw): %s on line %d +Warning: popen(abc.txt,rw): Invalid mode in %s on line %d bool(false) --- Done --- |