Skip to content

Commit ea4cb79

Browse files
ericsalocopybara-github
authored andcommitted
fix Python bug with required fields
https://github.com/protocolbuffers/upb/issues/1220 There were two bugs here: Python was incorrectly mandating that a required field be set during assignment, and it was also incorrectly assuming a non-NULL return from an internal function call. PiperOrigin-RevId: 518561818
1 parent 4e25ba4 commit ea4cb79

File tree

2 files changed

+20
-4
lines changed

2 files changed

+20
-4
lines changed

python/message.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -447,16 +447,18 @@ static bool PyUpb_Message_InitRepeatedAttribute(PyObject* _self, PyObject* name,
447447
return ok;
448448
}
449449

450+
static PyObject* PyUpb_Message_MergePartialFrom(PyObject*, PyObject*);
451+
450452
static bool PyUpb_Message_InitMessageAttribute(PyObject* _self, PyObject* name,
451453
PyObject* value) {
452454
PyObject* submsg = PyUpb_Message_GetAttr(_self, name);
453455
if (!submsg) return -1;
454456
assert(!PyErr_Occurred());
455457
bool ok;
456458
if (PyUpb_Message_TryCheck(value)) {
457-
PyObject* tmp = PyUpb_Message_MergeFrom(submsg, value);
459+
PyObject* tmp = PyUpb_Message_MergePartialFrom(submsg, value);
458460
ok = tmp != NULL;
459-
Py_DECREF(tmp);
461+
Py_XDECREF(tmp);
460462
} else if (PyDict_Check(value)) {
461463
assert(!PyErr_Occurred());
462464
ok = PyUpb_Message_InitAttributes(submsg, NULL, value) >= 0;
@@ -1184,7 +1186,8 @@ static PyObject* PyUpb_Message_ListFields(PyObject* _self, PyObject* arg) {
11841186
return NULL;
11851187
}
11861188

1187-
PyObject* PyUpb_Message_MergeFrom(PyObject* self, PyObject* arg) {
1189+
static PyObject* PyUpb_Message_MergeInternal(PyObject* self, PyObject* arg,
1190+
bool check_required) {
11881191
if (self->ob_type != arg->ob_type) {
11891192
PyErr_Format(PyExc_TypeError,
11901193
"Parameter to MergeFrom() must be instance of same class: "
@@ -1194,7 +1197,10 @@ PyObject* PyUpb_Message_MergeFrom(PyObject* self, PyObject* arg) {
11941197
}
11951198
// OPT: exit if src is empty.
11961199
PyObject* subargs = PyTuple_New(0);
1197-
PyObject* serialized = PyUpb_Message_SerializeToString(arg, subargs, NULL);
1200+
PyObject* serialized =
1201+
check_required
1202+
? PyUpb_Message_SerializeToString(arg, subargs, NULL)
1203+
: PyUpb_Message_SerializePartialToString(arg, subargs, NULL);
11981204
Py_DECREF(subargs);
11991205
if (!serialized) return NULL;
12001206
PyObject* ret = PyUpb_Message_MergeFromString(self, serialized);
@@ -1203,6 +1209,14 @@ PyObject* PyUpb_Message_MergeFrom(PyObject* self, PyObject* arg) {
12031209
Py_RETURN_NONE;
12041210
}
12051211

1212+
PyObject* PyUpb_Message_MergeFrom(PyObject* self, PyObject* arg) {
1213+
return PyUpb_Message_MergeInternal(self, arg, true);
1214+
}
1215+
1216+
static PyObject* PyUpb_Message_MergePartialFrom(PyObject* self, PyObject* arg) {
1217+
return PyUpb_Message_MergeInternal(self, arg, false);
1218+
}
1219+
12061220
static PyObject* PyUpb_Message_SetInParent(PyObject* _self, PyObject* arg) {
12071221
PyUpb_Message* self = (void*)_self;
12081222
PyUpb_Message_EnsureReified(self);

python/message.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ PyObject* PyUpb_Message_MergeFrom(PyObject* self, PyObject* arg);
6464
PyObject* PyUpb_Message_MergeFromString(PyObject* self, PyObject* arg);
6565
PyObject* PyUpb_Message_SerializeToString(PyObject* self, PyObject* args,
6666
PyObject* kwargs);
67+
PyObject* PyUpb_Message_SerializePartialToString(PyObject* self, PyObject* args,
68+
PyObject* kwargs);
6769

6870
// Sets fields of the message according to the attribuges in `kwargs`.
6971
int PyUpb_Message_InitAttributes(PyObject* _self, PyObject* args,

0 commit comments

Comments
 (0)