upb: fix a Python memory leak in ByteSize()

https://github.com/protocolbuffers/upb/issues/1243

PiperOrigin-RevId: 560873830
pull/13706/head
Eric Salo 2 years ago committed by Copybara-Service
parent 9274c2be9c
commit e45a6d5068
  1. 6
      upb/python/message.c
  2. 4
      upb/upb/util/required_fields.c
  3. 10
      upb/upb/util/required_fields_test.cc

@ -1431,9 +1431,10 @@ static PyObject* PyUpb_Message_FindInitializationErrors(PyObject* _self,
upb_Message* msg = PyUpb_Message_GetIfReified(_self); upb_Message* msg = PyUpb_Message_GetIfReified(_self);
const upb_MessageDef* msgdef = _PyUpb_Message_GetMsgdef(self); const upb_MessageDef* msgdef = _PyUpb_Message_GetMsgdef(self);
const upb_DefPool* ext_pool = upb_FileDef_Pool(upb_MessageDef_File(msgdef)); const upb_DefPool* ext_pool = upb_FileDef_Pool(upb_MessageDef_File(msgdef));
upb_FieldPathEntry* fields; upb_FieldPathEntry* fields_base;
PyObject* ret = PyList_New(0); PyObject* ret = PyList_New(0);
if (upb_util_HasUnsetRequired(msg, msgdef, ext_pool, &fields)) { if (upb_util_HasUnsetRequired(msg, msgdef, ext_pool, &fields_base)) {
upb_FieldPathEntry* fields = fields_base;
char* buf = NULL; char* buf = NULL;
size_t size = 0; size_t size = 0;
assert(fields->field); assert(fields->field);
@ -1453,6 +1454,7 @@ static PyObject* PyUpb_Message_FindInitializationErrors(PyObject* _self,
Py_DECREF(str); Py_DECREF(str);
} }
free(buf); free(buf);
free(fields_base);
} }
return ret; return ret;
} }

@ -303,11 +303,13 @@ bool upb_util_HasUnsetRequired(const upb_Message* msg, const upb_MessageDef* m,
upb_FieldPathVector_Init(&ctx.out_fields); upb_FieldPathVector_Init(&ctx.out_fields);
upb_util_FindUnsetRequiredInternal(&ctx, msg, m); upb_util_FindUnsetRequiredInternal(&ctx, msg, m);
free(ctx.stack.path); free(ctx.stack.path);
if (fields) {
if (ctx.has_unset_required && fields) {
upb_FieldPathVector_Reserve(&ctx, &ctx.out_fields, 1); upb_FieldPathVector_Reserve(&ctx, &ctx.out_fields, 1);
ctx.out_fields.path[ctx.out_fields.size] = ctx.out_fields.path[ctx.out_fields.size] =
(upb_FieldPathEntry){.field = NULL}; (upb_FieldPathEntry){.field = NULL};
*fields = ctx.out_fields.path; *fields = ctx.out_fields.path;
} }
return ctx.has_unset_required; return ctx.has_unset_required;
} }

@ -30,6 +30,8 @@
#include "upb/util/required_fields.h" #include "upb/util/required_fields.h"
#include <stdlib.h>
#include "gmock/gmock.h" #include "gmock/gmock.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
@ -73,11 +75,13 @@ void CheckRequired(absl::string_view json,
EXPECT_TRUE(upb_JsonDecode(json.data(), json.size(), test_msg, m.ptr(), EXPECT_TRUE(upb_JsonDecode(json.data(), json.size(), test_msg, m.ptr(),
defpool.ptr(), 0, arena.ptr(), status.ptr())) defpool.ptr(), 0, arena.ptr(), status.ptr()))
<< status.error_message(); << status.error_message();
upb_FieldPathEntry* entries; upb_FieldPathEntry* entries = nullptr;
EXPECT_EQ(!missing.empty(), upb_util_HasUnsetRequired( EXPECT_EQ(!missing.empty(), upb_util_HasUnsetRequired(
test_msg, m.ptr(), defpool.ptr(), &entries)); test_msg, m.ptr(), defpool.ptr(), &entries));
EXPECT_EQ(missing, PathsToText(entries)); if (entries) {
free(entries); EXPECT_EQ(missing, PathsToText(entries));
free(entries);
}
// Verify that we can pass a NULL pointer to entries when we don't care about // Verify that we can pass a NULL pointer to entries when we don't care about
// them. // them.

Loading…
Cancel
Save