Fix "missing required field" error with submessage callback (#544).
diff --git a/pb_decode.c b/pb_decode.c
index 84b0f3e..41d895d 100644
--- a/pb_decode.c
+++ b/pb_decode.c
@@ -1601,6 +1601,7 @@
static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_iter_t *field)
{
bool status = true;
+ bool submsg_consumed = false;
pb_istream_t substream;
if (!pb_make_string_substream(stream, &substream))
@@ -1632,11 +1633,16 @@
if (callback->funcs.decode)
{
status = callback->funcs.decode(&substream, field, &callback->arg);
+
+ if (substream.bytes_left == 0)
+ {
+ submsg_consumed = true;
+ }
}
}
/* Now decode the submessage contents */
- if (status)
+ if (status && !submsg_consumed)
{
status = pb_decode_inner(&substream, field->submsg_desc, field->pData, 0);
}
diff --git a/tests/regression/issue_544/SConscript b/tests/regression/issue_544/SConscript
new file mode 100644
index 0000000..4daf12c
--- /dev/null
+++ b/tests/regression/issue_544/SConscript
@@ -0,0 +1,8 @@
+# Regression test for #544:
+# Decoding whole submessage in submessage callback causes "missing required field"
+
+Import("env")
+env.NanopbProto("submsg_callback")
+
+test = env.Program(["submsg_callback.c", "submsg_callback.pb.c", "$COMMON/pb_encode.o", "$COMMON/pb_decode.o", "$COMMON/pb_common.o"])
+env.RunTest(test)
diff --git a/tests/regression/issue_544/submsg_callback.c b/tests/regression/issue_544/submsg_callback.c
new file mode 100644
index 0000000..938ba6c
--- /dev/null
+++ b/tests/regression/issue_544/submsg_callback.c
@@ -0,0 +1,57 @@
+#include "submsg_callback.pb.h"
+#include <pb_encode.h>
+#include <pb_decode.h>
+#include "unittests.h"
+
+bool msg_callback(pb_istream_t *stream, const pb_field_t *field, void **arg)
+{
+ /* This tests decoding the submessage already in the message level callback. */
+
+ SubMessage *submsg = (SubMessage*)field->pData;
+
+ if (!pb_decode(stream, SubMessage_fields, submsg))
+ PB_RETURN_ERROR(stream, "submsg decode failed");
+
+ if (submsg->foo != 1234)
+ PB_RETURN_ERROR(stream, "submsg.foo wrong value");
+
+ return true;
+}
+
+int main()
+{
+ int status = 0;
+ pb_byte_t buf[64];
+ size_t msglen;
+
+ {
+ pb_ostream_t ostream = pb_ostream_from_buffer(buf, sizeof(buf));
+ MyMessage msg = MyMessage_init_zero;
+
+ msg.which_oneof = MyMessage_submsg_tag;
+ msg.oneof.submsg.foo = 1234;
+
+ if (!pb_encode(&ostream, MyMessage_fields, &msg))
+ {
+ fprintf(stderr, "pb_encode() failed: %s\n", PB_GET_ERROR(&ostream));
+ return 1;
+ }
+
+ msglen = ostream.bytes_written;
+ TEST(msglen > 0);
+ }
+
+ {
+ pb_istream_t istream = pb_istream_from_buffer(buf, msglen);
+ MyMessage msg = MyMessage_init_zero;
+ msg.cb_oneof.funcs.decode = msg_callback;
+
+ if (!pb_decode(&istream, MyMessage_fields, &msg))
+ {
+ fprintf(stderr, "pb_decode() failed: %s\n", PB_GET_ERROR(&istream));
+ return 1;
+ }
+ }
+
+ return status;
+}
\ No newline at end of file
diff --git a/tests/regression/issue_544/submsg_callback.proto b/tests/regression/issue_544/submsg_callback.proto
new file mode 100644
index 0000000..50485d2
--- /dev/null
+++ b/tests/regression/issue_544/submsg_callback.proto
@@ -0,0 +1,13 @@
+syntax = "proto2";
+
+import "nanopb.proto";
+
+message SubMessage {
+ required uint32 foo = 1;
+}
+
+message MyMessage {
+ oneof oneof {
+ SubMessage submsg = 1 [(nanopb).submsg_callback = true];
+ }
+}