Fix memory leak

This fixes oss-fuzz #47088
This commit is contained in:
Dmitry Stogov 2022-05-11 11:43:01 +03:00
parent 82eea0efc9
commit b1b79c74fb
4 changed files with 19 additions and 2 deletions

View File

@ -0,0 +1,13 @@
--TEST--
Ownership of constant expression inhereted from interface should be transfered to class
--FILE--
<?php
interface I {
const X2 = 'X' . self::Y2;
const Y2 = 'Y';
}
eval('class B implements I{}');
var_dump(B::X2);
?>
--EXPECT--
string(2) "XY"

View File

@ -26,6 +26,7 @@
#define CONST_PERSISTENT (1<<0) /* Persistent */
#define CONST_NO_FILE_CACHE (1<<1) /* Can't be saved in file cache */
#define CONST_DEPRECATED (1<<2) /* Deprecated */
#define CONST_OWNED (1<<3) /* constant should be destroyed together with class */
#define PHP_USER_CONSTANT 0x7fffff /* a constant defined in user space */

View File

@ -28,6 +28,7 @@
#include "zend_exceptions.h"
#include "zend_enum.h"
#include "zend_attributes.h"
#include "zend_constants.h"
ZEND_API zend_class_entry* (*zend_inheritance_cache_get)(zend_class_entry *ce, zend_class_entry *parent, zend_class_entry **traits_and_interfaces) = NULL;
ZEND_API zend_class_entry* (*zend_inheritance_cache_add)(zend_class_entry *ce, zend_class_entry *proto, zend_class_entry *parent, zend_class_entry **traits_and_interfaces, HashTable *dependencies) = NULL;
@ -1635,6 +1636,7 @@ static void do_inherit_iface_constant(zend_string *name, zend_class_constant *c,
ct = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant));
memcpy(ct, c, sizeof(zend_class_constant));
c = ct;
Z_CONSTANT_FLAGS(c->value) |= CONST_OWNED;
}
}
if (ce->type & ZEND_INTERNAL_CLASS) {

View File

@ -26,6 +26,7 @@
#include "zend_extensions.h"
#include "zend_API.h"
#include "zend_sort.h"
#include "zend_constants.h"
#include "zend_vm.h"
@ -255,7 +256,7 @@ ZEND_API void zend_cleanup_mutable_class_data(zend_class_entry *ce)
zend_class_constant *c;
ZEND_HASH_FOREACH_PTR(constants_table, c) {
if (c->ce == ce) {
if (c->ce == ce || (Z_CONSTANT_FLAGS(c->value) & CONST_OWNED)) {
zval_ptr_dtor_nogc(&c->value);
}
} ZEND_HASH_FOREACH_END();
@ -387,7 +388,7 @@ ZEND_API void destroy_zend_class(zval *zv)
zend_class_constant *c;
ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) {
if (c->ce == ce) {
if (c->ce == ce || (Z_CONSTANT_FLAGS(c->value) & CONST_OWNED)) {
zval_ptr_dtor_nogc(&c->value);
if (c->doc_comment) {
zend_string_release_ex(c->doc_comment, 0);