From 738946df315c53b963c8ffce3a3a3828256349fc Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 10 Jul 2023 13:25:34 +0200 Subject: [PATCH 1/4] Fix buffer mismanagement in phar_dir_read() Fixes GHSA-jqcx-ccgc-xwhv. (cherry picked from commit 80316123f3e9dcce8ac419bd9dd43546e2ccb5ef) (cherry picked from commit c398fe98c044c8e7c23135acdc38d4ef7bedc983) (cherry picked from commit 3f14261065e4c0552afa9cb16411475050a41c2c) (cherry picked from commit f8f433d0d8eaac21af4f4532496d33f9c2b381d6) (cherry picked from commit f41261182dad0f831d8727967c127da1f08c8ce5) (cherry picked from commit 47388f7e4e1369feeffdb6976b469e7dfa72d9cb) --- ext/phar/dirstream.c | 16 +++++++++------ ext/phar/tests/GHSA-jqcx-ccgc-xwhv.phpt | 27 +++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 ext/phar/tests/GHSA-jqcx-ccgc-xwhv.phpt diff --git a/ext/phar/dirstream.c b/ext/phar/dirstream.c index f843501b58..411a2b0692 100644 --- a/ext/phar/dirstream.c +++ b/ext/phar/dirstream.c @@ -92,26 +92,30 @@ static int phar_dir_seek(php_stream *stream, off_t offset, int whence, off_t *ne */ static size_t phar_dir_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) /* {{{ */ { - size_t to_read; HashTable *data = (HashTable *)stream->abstract; char *str_key; uint keylen; ulong unused; + if (count != sizeof(php_stream_dirent)) { + return -1; + } + if (HASH_KEY_NON_EXISTENT == zend_hash_get_current_key_ex(data, &str_key, &keylen, &unused, 0, NULL)) { return 0; } zend_hash_move_forward(data); - to_read = MIN(keylen, count); - if (to_read == 0 || count < keylen) { + php_stream_dirent *dirent = (php_stream_dirent *) buf; + + if (sizeof(dirent->d_name) <= keylen) { return 0; } - memset(buf, 0, sizeof(php_stream_dirent)); - memcpy(((php_stream_dirent *) buf)->d_name, str_key, to_read); - ((php_stream_dirent *) buf)->d_name[to_read + 1] = '\0'; + memset(dirent, 0, sizeof(php_stream_dirent)); + memcpy(dirent->d_name, str_key, keylen); + dirent->d_name[keylen] = '\0'; return sizeof(php_stream_dirent); } diff --git a/ext/phar/tests/GHSA-jqcx-ccgc-xwhv.phpt b/ext/phar/tests/GHSA-jqcx-ccgc-xwhv.phpt new file mode 100644 index 0000000000..4e12f05fb6 --- /dev/null +++ b/ext/phar/tests/GHSA-jqcx-ccgc-xwhv.phpt @@ -0,0 +1,27 @@ +--TEST-- +GHSA-jqcx-ccgc-xwhv (Buffer overflow and overread in phar_dir_read()) +--SKIPIF-- + +--INI-- +phar.readonly=0 +--FILE-- +startBuffering(); +$phar->addFromString(str_repeat('A', PHP_MAXPATHLEN - 1), 'This is the content of file 1.'); +$phar->addFromString(str_repeat('B', PHP_MAXPATHLEN - 1).'C', 'This is the content of file 2.'); +$phar->stopBuffering(); + +$handle = opendir('phar://' . __DIR__ . '/GHSA-jqcx-ccgc-xwhv.phar'); +var_dump(strlen(readdir($handle))); +// Must not be a string of length PHP_MAXPATHLEN+1 +var_dump(readdir($handle)); +closedir($handle); +?> +--CLEAN-- + +--EXPECTF-- +int(%d) +bool(false) -- 2.41.0