diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index e2f36f1c7b24..8b467a9abc8f 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -3560,9 +3560,23 @@ PHP_METHOD(Phar, copy) newentry.filename_len = tmp_len; newentry.fp_refcount = 0; + if (newentry.link) { + newentry.link = estrdup(newentry.link); + } + + if (newentry.tmp) { + newentry.tmp = estrdup(newentry.tmp); + } + if (oldentry->fp_type != PHAR_FP) { if (FAILURE == phar_copy_entry_fp(oldentry, &newentry, &error)) { efree(newentry.filename); + if (newentry.link) { + efree(newentry.link); + } + if (newentry.tmp) { + efree(newentry.tmp); + } php_stream_close(newentry.fp); zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error); efree(error); diff --git a/ext/phar/tests/gh25092.phpt b/ext/phar/tests/gh25092.phpt new file mode 100644 index 000000000000..604094d76362 --- /dev/null +++ b/ext/phar/tests/gh25092.phpt @@ -0,0 +1,62 @@ +--TEST-- +GH-25092 (Double free in Phar::copy() on link and mounted entries) +--EXTENSIONS-- +phar +--INI-- +phar.readonly=0 +--FILE-- +copy('l', 'l2'); +unset($t); + +$t = new PharData($tar); +var_dump(isset($t['l']), isset($t['l2'])); +unset($t); + +$phar = __DIR__ . '/gh25092.phar'; +file_put_contents(__DIR__ . '/gh25092.txt', 'hello'); + +$p = new Phar($phar); +$p->addFromString('x.txt', 'x'); +$p->setStub(''); +unset($p); + +$p = new Phar($phar); +Phar::mount('phar://' . $phar . '/m.txt', __DIR__ . '/gh25092.txt'); +$p->copy('m.txt', 'c.txt'); +var_dump(isset($p['c.txt'])); +?> +--CLEAN-- + +--EXPECT-- +bool(true) +bool(true) +bool(true)