Bug #79820 [Opn]: double-free causing heap corruption

From: Date: Wed, 15 Jul 2020 08:39:46 +0000
Subject: Bug #79820 [Opn]: double-free causing heap corruption
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-228057@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=79820&edit=1 ID: 79820 Updated by: nikic@php.net Reported by: christopher dot broadbent at zencontrol dot com Summary: double-free causing heap corruption Status: Open Type: Bug Package: Reproducible crash Operating System: linux debian buster PHP Version: 7.4.7 Block user comment: N Private report: N New Comment: Right you are! Minimal reproducer: <?php class Test { public stdClass $prop; } $rp = new ReflectionProperty(Test::class, 'prop'); $test = new Test; $test->prop = new stdClass; var_dump($rp->getType()->getName()); For PHP 8 this has already been fixed by https://github.com/php/php-src/commit/0e3045ae69d1b80c21b2779df721a4ad8bcda401. Previous Comments: ------------------------------------------------------------------------ [2020-07-15 05:44:51] chris-broadbent at zencontrol dot com The following patch has been added/updated: Patch Name: 0001-Add-refs-to-prop-names-to-avoid-use-after-free Revision: 1594791891 URL: https://bugs.php.net/patch-display.php?bug=79820&patch=0001-Add-refs-to-prop-names-to-avoid-use-after-free&revision=1594791891 ------------------------------------------------------------------------ [2020-07-14 23:53:50] christopher dot broadbent at zencontrol dot com I've made a change to php_reflecation.c lines 5281 to 5302, on 7.4.8 release, inside reflection_property____construct reference = (property_reference*) emalloc(sizeof(property_reference)); if (dynam_prop) { reference->prop.flags = ZEND_ACC_PUBLIC; reference->prop.name = name; reference->prop.doc_comment = NULL; reference->prop.ce = ce; reference->dynamic = 1; } else { reference->prop = *property_info; reference->dynamic = 0; + if (ZEND_TYPE_IS_NAME(reference->prop.type)) { + zend_string_addref(ZEND_TYPE_NAME(reference->prop.type)); + } } reference->unmangled_name = zend_string_copy(name); intern->ptr = reference; intern->ref_type = REF_TYPE_PROPERTY; intern->ce = ce; intern->ignore_visibility = 0; } This fixes the segfault in all the reproduction cases we've got, but I'm not familiar enough with the rest of the code to know if this is correct or causes leaks. ------------------------------------------------------------------------ [2020-07-14 23:27:12] christopher dot broadbent at zencontrol dot com Sorry, I meant to say bump the ref counters on reference->prop.type ------------------------------------------------------------------------ [2020-07-14 23:22:18] christopher dot broadbent at zencontrol dot com This is probably my inexperience with the code-base, but shouldn't the implementation for ZEND_METHOD(reflection_property, __construct) by increment the ref-count for the value copied by reference->prop = *property_info; when dynam_prop is false? It seems to be the thing keeping a reference around to the deallocated string, causing the use-after-free, and I can't see anywhere in the code path where it bumps the reference count. ------------------------------------------------------------------------ [2020-07-14 07:48:04] ondrej@php.net > On which version/commit of PHP were the gdb backtraces gathered? I can't find > any > version of PHP 7.4 that has a zend_string_release call in php_reflection.c:225. The valgrind trace > looks more plausible. If you look carefully, the backtrace matches the function with it's location and zend_string_release is always inlined, so the php_reflection.c:225 is just a red herring as it just got inlined (and the line number marks the location of the affected block where it is used). The packages don't patch php_reflection.c at all. ------------------------------------------------------------------------ The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online at https://bugs.php.net/bug.php?id=79820 -- Edit this bug report at https://bugs.php.net/bug.php?id=79820&edit=1

« previous php.bugs (#228057) next »