diff --git a/NEWS b/NEWS index ca9ac46ebae..70829cbc981 100644 --- a/NEWS +++ b/NEWS @@ -63,6 +63,9 @@ PHP NEWS . Fixed bug GH-12974 (Apache crashes on shutdown when using pg_pconnect()). (nielsdos) +- Phar: + . Fixed bug #77432 (Segmentation fault on including phar file). (nielsdos) + - PHPDBG: . Fixed bug GH-12962 (Double free of init_file in phpdbg_prompt.c). (nielsdos) diff --git a/ext/phar/stream.c b/ext/phar/stream.c index e400699780e..3288aa4c2d1 100644 --- a/ext/phar/stream.c +++ b/ext/phar/stream.c @@ -254,6 +254,17 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, const cha php_url_free(resource); goto phar_stub; } else { + php_stream *stream = phar_get_pharfp(phar); + if (stream == NULL) { + if (UNEXPECTED(FAILURE == phar_open_archive_fp(phar))) { + php_stream_wrapper_log_error(wrapper, options, "phar error: could not reopen phar \"%s\"", ZSTR_VAL(resource->host)); + efree(internal_file); + php_url_free(resource); + return NULL; + } + stream = phar_get_pharfp(phar); + } + phar_entry_info *entry; entry = (phar_entry_info *) ecalloc(1, sizeof(phar_entry_info)); @@ -266,7 +277,7 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, const cha entry->is_crc_checked = 1; idata = (phar_entry_data *) ecalloc(1, sizeof(phar_entry_data)); - idata->fp = phar_get_pharfp(phar); + idata->fp = stream; idata->phar = phar; idata->internal_file = entry; if (!phar->is_persistent) { diff --git a/ext/phar/tests/bug77432.phpt b/ext/phar/tests/bug77432.phpt new file mode 100644 index 00000000000..5e4d79c4a3d --- /dev/null +++ b/ext/phar/tests/bug77432.phpt @@ -0,0 +1,46 @@ +--TEST-- +Bug #77432 (Segmentation fault on including phar file) +--EXTENSIONS-- +phar +--INI-- +phar.readonly=0 +--FILE-- +startBuffering(); +$phar->addFromString('test.txt', 'text'); +$phar->setStub(''); +$phar->stopBuffering(); +unset($phar); + +echo "--- Include 1 ---\n"; +include("phar://" . $filename); +echo "--- Include 2 ---\n"; +// Note: will warn because the halting offset is redefined, but won't display the name because "zend_mangle_property_name" starts the name with \0 +// However, this is just the easiest way to reproduce it, so go with this test. +include("phar://" . $filename); +echo "--- After unlink ---\n"; +unlink($filename); +// This will just fail, as it should, but it is here to test the reopen error-handling path. +include("phar://" . $filename); + +?> +--CLEAN-- + +--EXPECTF-- +--- Include 1 --- +hello world +--- Include 2 --- + +Warning: Constant already defined in %s on line %d +hello world +--- After unlink --- + +Warning: include(%sbug77432.phar): Failed to open stream: phar error: could not reopen phar "%sbug77432.phar" in %s on line %d + +Warning: include(): Failed opening '%sbug77432.phar' for inclusion (include_path='.:') in %s on line %d