Fixed PHP SEGV by not writing to shared memory for zend_class_entry.

pull/9996/head
Joshua Haberman 3 years ago
parent fe3d67cb8e
commit a04d00312f
  1. 5
      php/ext/google/protobuf/message.c
  2. 16
      php/ext/google/protobuf/protobuf.c
  3. 2
      php/ext/google/protobuf/protobuf.h

@ -603,10 +603,9 @@ PHP_METHOD(Message, __construct) {
// will trigger an infinite construction loop and blow the stack. We // will trigger an infinite construction loop and blow the stack. We
// temporarily clear create_object to break this loop (see check in // temporarily clear create_object to break this loop (see check in
// NameMap_GetMessage()). // NameMap_GetMessage()).
PBPHP_ASSERT(ce->create_object == Message_create); NameMap_EnterConstructor(ce);
ce->create_object = NULL;
desc = Descriptor_GetFromClassEntry(ce); desc = Descriptor_GetFromClassEntry(ce);
ce->create_object = Message_create; NameMap_ExitConstructor(ce);
if (!desc) { if (!desc) {
zend_throw_exception_ex( zend_throw_exception_ex(

@ -56,6 +56,9 @@ ZEND_BEGIN_MODULE_GLOBALS(protobuf)
// Set by the user to make the descriptor pool persist between requests. // Set by the user to make the descriptor pool persist between requests.
zend_bool keep_descriptor_pool_after_request; zend_bool keep_descriptor_pool_after_request;
// Set by the user to make the descriptor pool persist between requests.
zend_class_entry* constructing_class;
// A upb_DefPool that we are saving for the next request so that we don't have // A upb_DefPool that we are saving for the next request so that we don't have
// to rebuild it from scratch. When keep_descriptor_pool_after_request==true, // to rebuild it from scratch. When keep_descriptor_pool_after_request==true,
// we steal the upb_DefPool from the global DescriptorPool object just before // we steal the upb_DefPool from the global DescriptorPool object just before
@ -173,6 +176,7 @@ static PHP_RINIT_FUNCTION(protobuf) {
zend_hash_init(&PROTOBUF_G(object_cache), 64, NULL, NULL, 0); zend_hash_init(&PROTOBUF_G(object_cache), 64, NULL, NULL, 0);
zend_hash_init(&PROTOBUF_G(descriptors), 64, NULL, ZVAL_PTR_DTOR, 0); zend_hash_init(&PROTOBUF_G(descriptors), 64, NULL, ZVAL_PTR_DTOR, 0);
PROTOBUF_G(constructing_class) = NULL;
return SUCCESS; return SUCCESS;
} }
@ -253,7 +257,7 @@ const upb_MessageDef *NameMap_GetMessage(zend_class_entry *ce) {
const upb_MessageDef *ret = const upb_MessageDef *ret =
zend_hash_find_ptr(&PROTOBUF_G(name_msg_cache), ce->name); zend_hash_find_ptr(&PROTOBUF_G(name_msg_cache), ce->name);
if (!ret && ce->create_object) { if (!ret && ce->create_object && ce != PROTOBUF_G(constructing_class)) {
#if PHP_VERSION_ID < 80000 #if PHP_VERSION_ID < 80000
zval tmp; zval tmp;
zval zv; zval zv;
@ -279,6 +283,16 @@ const upb_EnumDef *NameMap_GetEnum(zend_class_entry *ce) {
return ret; return ret;
} }
void NameMap_EnterConstructor(zend_class_entry* ce) {
assert(!PROTOBUF_G(constructing_class));
PROTOBUF_G(constructing_class) = ce;
}
void NameMap_ExitConstructor(zend_class_entry* ce) {
assert(PROTOBUF_G(constructing_class) == ce);
PROTOBUF_G(constructing_class) = NULL;
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Module init. // Module init.
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

@ -155,6 +155,8 @@ void NameMap_AddMessage(const upb_MessageDef *m);
void NameMap_AddEnum(const upb_EnumDef *m); void NameMap_AddEnum(const upb_EnumDef *m);
const upb_MessageDef *NameMap_GetMessage(zend_class_entry *ce); const upb_MessageDef *NameMap_GetMessage(zend_class_entry *ce);
const upb_EnumDef *NameMap_GetEnum(zend_class_entry *ce); const upb_EnumDef *NameMap_GetEnum(zend_class_entry *ce);
void NameMap_EnterConstructor(zend_class_entry* ce);
void NameMap_ExitConstructor(zend_class_entry* ce);
// Add this descriptor object to the global list of descriptors that will be // Add this descriptor object to the global list of descriptors that will be
// kept alive for the duration of the request but destroyed when the request // kept alive for the duration of the request but destroyed when the request

Loading…
Cancel
Save