diff --git a/NEWS b/NEWS index 41368234794..0e57f4ef489 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,10 @@ PHP NEWS . Fixed bug GH-10495 (feof on OpenSSL stream hangs indefinitely). (Jakub Zelenka) +- Phar: + . Fixed bug GH-13836 (Renaming a file in a Phar to an already existing + filename causes a NULL pointer dereference). (nielsdos) + - PHPDBG: . Fixed bug GH-13827 (Null pointer access of type 'zval' in phpdbg_frame). (nielsdos) diff --git a/ext/phar/stream.c b/ext/phar/stream.c index 3288aa4c2d1..752e15ed717 100644 --- a/ext/phar/stream.c +++ b/ext/phar/stream.c @@ -858,8 +858,9 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from entry->link = entry->tmp = NULL; source = entry; - /* add to the manifest, and then store the pointer to the new guy in entry */ - entry = zend_hash_str_add_mem(&(phar->manifest), ZSTR_VAL(resource_to->path)+1, ZSTR_LEN(resource_to->path)-1, (void **)&new, sizeof(phar_entry_info)); + /* add to the manifest, and then store the pointer to the new guy in entry + * if it already exists, we overwrite the destination like what copy('phar://...', 'phar://...') does. */ + entry = zend_hash_str_update_mem(&(phar->manifest), ZSTR_VAL(resource_to->path)+1, ZSTR_LEN(resource_to->path)-1, (void **)&new, sizeof(phar_entry_info)); entry->filename = estrndup(ZSTR_VAL(resource_to->path)+1, ZSTR_LEN(resource_to->path)-1); if (FAILURE == phar_copy_entry_fp(source, entry, &error)) { diff --git a/ext/phar/tests/gh13833.phpt b/ext/phar/tests/gh13833.phpt new file mode 100644 index 00000000000..d1b79d033e0 --- /dev/null +++ b/ext/phar/tests/gh13833.phpt @@ -0,0 +1,33 @@ +--TEST-- +GH-13836 (Renaming a file in a Phar to an already existing filename causes a NULL pointer dereference) +--EXTENSIONS-- +phar +--INI-- +phar.require_hash=0 +phar.readonly=0 +--FILE-- + +--CLEAN-- + +--EXPECTF-- +bool(true) +bool(false) +object(PharFileInfo)#2 (2) { + ["pathName":"SplFileInfo":private]=> + string(%d) "phar://%sgh13836.phar/y" + ["fileName":"SplFileInfo":private]=> + string(1) "y" +}