Add upb_MiniTable_FindUnknown depth_limit parameter.
Fix UpbMessageIsEqual IsMap fallthrough.
PiperOrigin-RevId: 522961305
diff --git a/BUILD b/BUILD
index 0985927..24bde07 100644
--- a/BUILD
+++ b/BUILD
@@ -139,6 +139,7 @@
"upb/string_view.h",
"upb/upb.h",
"upb/upb.hpp",
+ "upb/wire/common.h",
"upb/wire/decode.h",
"upb/wire/encode.h",
],
@@ -880,6 +881,7 @@
"upb/wire/encode.c",
],
hdrs = [
+ "upb/wire/common.h",
"upb/wire/common_internal.h",
"upb/wire/decode.h",
"upb/wire/decode_fast.h",
diff --git a/python/message.c b/python/message.c
index 753cc74..2fe5126 100644
--- a/python/message.c
+++ b/python/message.c
@@ -36,6 +36,7 @@
#include "upb/reflection/message.h"
#include "upb/text/encode.h"
#include "upb/util/required_fields.h"
+#include "upb/wire/common.h"
static const upb_MessageDef* PyUpb_MessageMeta_GetMsgdef(PyObject* cls);
static PyObject* PyUpb_MessageMeta_GetAttr(PyObject* self, PyObject* name);
@@ -1254,8 +1255,9 @@
const upb_MiniTable* layout = upb_MessageDef_MiniTable(msgdef);
upb_Arena* arena = PyUpb_Arena_Get(self->arena);
PyUpb_ModuleState* state = PyUpb_ModuleState_Get();
- int options =
- UPB_DECODE_MAXDEPTH(state->allow_oversize_protos ? UINT32_MAX : 100);
+ int options = upb_DecodeOptions_MaxDepth(
+ state->allow_oversize_protos ? UINT16_MAX
+ : kUpb_WireFormat_DefaultDepthLimit);
upb_DecodeStatus status =
upb_Decode(buf, size, self->ptr.msg, layout, extreg, options, arena);
Py_XDECREF(bytes);
diff --git a/upb/message/accessors.c b/upb/message/accessors.c
index 2ed872a..c10ffec 100644
--- a/upb/message/accessors.c
+++ b/upb/message/accessors.c
@@ -32,6 +32,7 @@
#include "upb/collections/map.h"
#include "upb/message/message.h"
#include "upb/mini_table/field_internal.h"
+#include "upb/wire/common.h"
#include "upb/wire/decode.h"
#include "upb/wire/encode.h"
#include "upb/wire/eps_copy_input_stream.h"
@@ -83,7 +84,8 @@
// Check unknown fields, if available promote.
int field_number = ext_table->field.number;
- upb_FindUnknownRet result = upb_MiniTable_FindUnknown(msg, field_number);
+ upb_FindUnknownRet result = upb_MiniTable_FindUnknown(
+ msg, field_number, kUpb_WireFormat_DefaultDepthLimit);
if (result.status != kUpb_FindUnknown_Ok) {
return kUpb_GetExtension_NotPresent;
}
@@ -134,7 +136,8 @@
return kUpb_GetExtensionAsBytes_Ok;
}
int field_number = ext_table->field.number;
- upb_FindUnknownRet result = upb_MiniTable_FindUnknown(msg, field_number);
+ upb_FindUnknownRet result = upb_MiniTable_FindUnknown(
+ msg, field_number, upb_DecodeOptions_GetMaxDepth(encode_options));
if (result.status != kUpb_FindUnknown_Ok) {
return kUpb_GetExtensionAsBytes_NotPresent;
}
@@ -153,8 +156,8 @@
}
upb_FindUnknownRet upb_MiniTable_FindUnknown(const upb_Message* msg,
- uint32_t field_number) {
- const int depth_limit = 100; // TODO: this should be a parameter
+ uint32_t field_number,
+ int depth_limit) {
size_t size;
upb_FindUnknownRet ret;
@@ -204,7 +207,8 @@
upb_UnknownToMessageRet ret;
ret.status = kUpb_UnknownToMessage_Ok;
do {
- unknown = upb_MiniTable_FindUnknown(msg, field->number);
+ unknown = upb_MiniTable_FindUnknown(
+ msg, field->number, upb_DecodeOptions_GetMaxDepth(decode_options));
switch (unknown.status) {
case kUpb_FindUnknown_Ok: {
const char* unknown_data = unknown.ptr;
@@ -250,7 +254,8 @@
// Find all unknowns with given field number and parse.
upb_FindUnknownRet unknown;
do {
- unknown = upb_MiniTable_FindUnknown(msg, field->number);
+ unknown = upb_MiniTable_FindUnknown(
+ msg, field->number, upb_DecodeOptions_GetMaxDepth(decode_options));
if (unknown.status == kUpb_FindUnknown_Ok) {
upb_UnknownToMessageRet ret = upb_MiniTable_ParseUnknownMessage(
unknown.ptr, unknown.len, mini_table,
@@ -314,7 +319,8 @@
// Find all unknowns with given field number and parse.
upb_FindUnknownRet unknown;
while (1) {
- unknown = upb_MiniTable_FindUnknown(msg, field->number);
+ unknown = upb_MiniTable_FindUnknown(
+ msg, field->number, upb_DecodeOptions_GetMaxDepth(decode_options));
if (unknown.status != kUpb_FindUnknown_Ok) break;
upb_UnknownToMessageRet ret = upb_MiniTable_ParseUnknownMessage(
unknown.ptr, unknown.len, map_entry_mini_table,
diff --git a/upb/message/accessors.h b/upb/message/accessors.h
index 6b56e58..74ca1f2 100644
--- a/upb/message/accessors.h
+++ b/upb/message/accessors.h
@@ -708,7 +708,8 @@
// Finds first occurrence of unknown data by tag id in message.
upb_FindUnknownRet upb_MiniTable_FindUnknown(const upb_Message* msg,
- uint32_t field_number);
+ uint32_t field_number,
+ int depth_limit);
typedef enum {
kUpb_UnknownToMessage_Ok,
diff --git a/upb/message/accessors_test.cc b/upb/message/accessors_test.cc
index d299acd..a0dece4 100644
--- a/upb/message/accessors_test.cc
+++ b/upb/message/accessors_test.cc
@@ -33,6 +33,8 @@
#include "upb/message/accessors.h"
+#include <string>
+
#include "gtest/gtest.h"
#include "google/protobuf/test_messages_proto2.upb.h"
#include "google/protobuf/test_messages_proto3.upb.h"
@@ -44,6 +46,7 @@
#include "upb/mini_table/field_internal.h"
#include "upb/test/test.upb.h"
#include "upb/upb.h"
+#include "upb/wire/common.h"
#include "upb/wire/decode.h"
namespace {
@@ -163,7 +166,7 @@
0, protobuf_test_messages_proto2_TestAllTypesProto2_optional_int32(msg));
EXPECT_EQ(0, upb_Message_GetInt32(msg, optional_int32_field, 0));
- upb_Message_SetInt32(msg, optional_int32_field, kTestInt32, NULL);
+ upb_Message_SetInt32(msg, optional_int32_field, kTestInt32, nullptr);
EXPECT_EQ(true, upb_Message_HasField(msg, optional_int32_field));
EXPECT_EQ(kTestInt32, upb_Message_GetInt32(msg, optional_int32_field, 0));
EXPECT_EQ(
@@ -176,7 +179,7 @@
EXPECT_EQ(
0, protobuf_test_messages_proto2_TestAllTypesProto2_optional_uint32(msg));
EXPECT_EQ(0, upb_Message_GetUInt32(msg, optional_uint32_field, 0));
- upb_Message_SetUInt32(msg, optional_uint32_field, kTestUInt32, NULL);
+ upb_Message_SetUInt32(msg, optional_uint32_field, kTestUInt32, nullptr);
EXPECT_EQ(kTestUInt32, upb_Message_GetUInt32(msg, optional_uint32_field, 0));
EXPECT_EQ(
kTestUInt32,
@@ -197,14 +200,14 @@
EXPECT_EQ(
0, protobuf_test_messages_proto3_TestAllTypesProto3_optional_int64(msg));
- upb_Message_SetInt64(msg, optional_int64_field, -1, NULL);
+ upb_Message_SetInt64(msg, optional_int64_field, -1, nullptr);
EXPECT_EQ(
-1, protobuf_test_messages_proto3_TestAllTypesProto3_optional_int64(msg));
EXPECT_EQ(-1, upb_Message_GetInt64(msg, optional_int64_field, 0));
EXPECT_EQ(
0, protobuf_test_messages_proto3_TestAllTypesProto3_optional_uint64(msg));
- upb_Message_SetUInt64(msg, optional_uint64_field, kTestUInt64, NULL);
+ upb_Message_SetUInt64(msg, optional_uint64_field, kTestUInt64, nullptr);
EXPECT_EQ(
kTestUInt64,
protobuf_test_messages_proto3_TestAllTypesProto3_optional_uint64(msg));
@@ -239,7 +242,7 @@
protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_string(
msg));
upb_Message_SetString(msg, optional_string_field,
- upb_StringView_FromString(kTestStr2), NULL);
+ upb_StringView_FromString(kTestStr2), nullptr);
EXPECT_EQ(true, upb_Message_HasField(msg, optional_string_field));
EXPECT_EQ(
true,
@@ -261,8 +264,8 @@
find_proto2_field(kFieldOptionalNestedMessage);
const upb_Message* test_message =
- upb_Message_GetMessage(msg, optional_message_field, NULL);
- EXPECT_EQ(NULL, test_message);
+ upb_Message_GetMessage(msg, optional_message_field, nullptr);
+ EXPECT_EQ(nullptr, test_message);
EXPECT_EQ(false, upb_Message_HasField(msg, optional_message_field));
@@ -277,8 +280,8 @@
// Read back using mini table API.
const upb_Message* sub_message =
- upb_Message_GetMessage(msg, optional_message_field, NULL);
- EXPECT_EQ(true, sub_message != NULL);
+ upb_Message_GetMessage(msg, optional_message_field, nullptr);
+ EXPECT_EQ(true, sub_message != nullptr);
const upb_MiniTableField* nested_message_a_field =
upb_MiniTable_FindFieldByNumber(
@@ -288,14 +291,15 @@
upb_Message_ClearField(msg, optional_message_field);
EXPECT_EQ(
- NULL,
+ nullptr,
protobuf_test_messages_proto2_TestAllTypesProto2_optional_nested_message(
msg));
EXPECT_EQ(false, upb_Message_HasField(msg, optional_message_field));
upb_Message* new_nested_message =
protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage_new(arena);
- upb_Message_SetInt32(new_nested_message, nested_message_a_field, 123, NULL);
+ upb_Message_SetInt32(new_nested_message, nested_message_a_field, 123,
+ nullptr);
upb_Message_SetMessage(
msg, &protobuf_test_messages_proto2_TestAllTypesProto2_msg_init,
optional_message_field, new_nested_message);
@@ -306,7 +310,7 @@
EXPECT_EQ(
true,
protobuf_test_messages_proto2_TestAllTypesProto2_optional_nested_message(
- msg) != NULL);
+ msg) != nullptr);
EXPECT_EQ(true, upb_Message_HasField(msg, optional_message_field));
EXPECT_EQ(123,
upb_Message_GetInt32(mutable_message, nested_message_a_field, 0));
@@ -328,8 +332,8 @@
&len);
// Test Get/Set Array values, validate with C API.
EXPECT_EQ(0, len);
- EXPECT_EQ(NULL, arr);
- EXPECT_EQ(NULL, upb_Message_GetArray(msg, repeated_int32_field));
+ EXPECT_EQ(nullptr, arr);
+ EXPECT_EQ(nullptr, upb_Message_GetArray(msg, repeated_int32_field));
protobuf_test_messages_proto2_TestAllTypesProto2_resize_repeated_int32(
msg, 10, arena);
int32_t* mutable_values =
@@ -361,7 +365,7 @@
protobuf_test_messages_proto2_TestAllTypesProto2_repeated_int32(msg,
&len);
EXPECT_EQ(0, len);
- EXPECT_EQ(true, zero_length_array != NULL);
+ EXPECT_EQ(true, zero_length_array != nullptr);
upb_Arena_Free(arena);
}
@@ -407,11 +411,13 @@
arena);
upb_FindUnknownRet result = upb_MiniTable_FindUnknown(
- base_msg, upb_test_ModelExtension1_model_ext_ext.field.number);
+ base_msg, upb_test_ModelExtension1_model_ext_ext.field.number,
+ kUpb_WireFormat_DefaultDepthLimit);
EXPECT_EQ(kUpb_FindUnknown_Ok, result.status);
result = upb_MiniTable_FindUnknown(
- base_msg, upb_test_ModelExtension2_model_ext_ext.field.number);
+ base_msg, upb_test_ModelExtension2_model_ext_ext.field.number,
+ kUpb_WireFormat_DefaultDepthLimit);
EXPECT_EQ(kUpb_FindUnknown_NotPresent, result.status);
upb_Arena_Free(arena);
@@ -639,21 +645,22 @@
int32_t val = upb_Message_GetInt32(
msg, upb_MiniTable_FindFieldByNumber(mini_table, 4), 0);
EXPECT_EQ(val, 11);
- upb_FindUnknownRet unknown = upb_MiniTable_FindUnknown(msg, 5);
+ upb_FindUnknownRet unknown =
+ upb_MiniTable_FindUnknown(msg, 5, kUpb_WireFormat_DefaultDepthLimit);
EXPECT_EQ(unknown.status, kUpb_FindUnknown_Ok);
// Update mini table and promote unknown to a message.
EXPECT_TRUE(upb_MiniTable_SetSubMessage(
mini_table, (upb_MiniTableField*)&mini_table->fields[1],
&upb_test_ModelWithExtensions_msg_init));
- const int decode_options =
- UPB_DECODE_MAXDEPTH(100); // UPB_DECODE_ALIAS disabled.
+ const int decode_options = upb_DecodeOptions_MaxDepth(
+ kUpb_WireFormat_DefaultDepthLimit); // UPB_DECODE_ALIAS disabled.
upb_UnknownToMessageRet promote_result =
upb_MiniTable_PromoteUnknownToMessage(
msg, mini_table, &mini_table->fields[1],
&upb_test_ModelWithExtensions_msg_init, decode_options, arena);
EXPECT_EQ(promote_result.status, kUpb_UnknownToMessage_Ok);
const upb_Message* promoted_message =
- upb_Message_GetMessage(msg, &mini_table->fields[1], NULL);
+ upb_Message_GetMessage(msg, &mini_table->fields[1], nullptr);
EXPECT_EQ(upb_test_ModelWithExtensions_random_int32(
(upb_test_ModelWithExtensions*)promoted_message),
12);
@@ -687,15 +694,16 @@
EXPECT_EQ(val, 123);
// Check that we have repeated field data in an unknown.
- upb_FindUnknownRet unknown = upb_MiniTable_FindUnknown(msg, 6);
+ upb_FindUnknownRet unknown =
+ upb_MiniTable_FindUnknown(msg, 6, kUpb_WireFormat_DefaultDepthLimit);
EXPECT_EQ(unknown.status, kUpb_FindUnknown_Ok);
// Update mini table and promote unknown to a message.
EXPECT_TRUE(upb_MiniTable_SetSubMessage(
mini_table, (upb_MiniTableField*)&mini_table->fields[2],
&upb_test_ModelWithExtensions_msg_init));
- const int decode_options =
- UPB_DECODE_MAXDEPTH(100); // UPB_DECODE_ALIAS disabled.
+ const int decode_options = upb_DecodeOptions_MaxDepth(
+ kUpb_WireFormat_DefaultDepthLimit); // UPB_DECODE_ALIAS disabled.
upb_UnknownToMessage_Status promote_result =
upb_MiniTable_PromoteUnknownToMessageArray(
msg, &mini_table->fields[2], &upb_test_ModelWithExtensions_msg_init,
@@ -734,23 +742,25 @@
upb_MiniTable* mini_table = CreateMiniTableWithEmptySubTablesForMaps(arena);
upb_MiniTable* map_entry_mini_table = CreateMapEntryMiniTable(arena);
upb_Message* msg = _upb_Message_New(mini_table, arena);
- upb_DecodeStatus decode_status = upb_Decode(serialized, serialized_size, msg,
- mini_table, nullptr, 0, arena);
+ const int decode_options =
+ upb_DecodeOptions_MaxDepth(kUpb_WireFormat_DefaultDepthLimit);
+ upb_DecodeStatus decode_status =
+ upb_Decode(serialized, serialized_size, msg, mini_table, nullptr,
+ decode_options, arena);
EXPECT_EQ(decode_status, kUpb_DecodeStatus_Ok);
int32_t val = upb_Message_GetInt32(
msg, upb_MiniTable_FindFieldByNumber(mini_table, 1), 0);
EXPECT_EQ(val, 123);
// Check that we have map data in an unknown.
- upb_FindUnknownRet unknown = upb_MiniTable_FindUnknown(msg, 3);
+ upb_FindUnknownRet unknown =
+ upb_MiniTable_FindUnknown(msg, 3, kUpb_WireFormat_DefaultDepthLimit);
EXPECT_EQ(unknown.status, kUpb_FindUnknown_Ok);
// Update mini table and promote unknown to a message.
EXPECT_TRUE(upb_MiniTable_SetSubMessage(
mini_table, (upb_MiniTableField*)&mini_table->fields[1],
map_entry_mini_table));
- const int decode_options =
- UPB_DECODE_MAXDEPTH(100); // UPB_DECODE_ALIAS disabled.
upb_UnknownToMessage_Status promote_result =
upb_MiniTable_PromoteUnknownToMap(msg, mini_table, &mini_table->fields[1],
decode_options, arena);
diff --git a/upb/wire/common.h b/upb/wire/common.h
new file mode 100644
index 0000000..c35b575
--- /dev/null
+++ b/upb/wire/common.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2009-2021, Google LLC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Google LLC nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef UPB_WIRE_COMMON_H_
+#define UPB_WIRE_COMMON_H_
+
+// Must be last.
+#include "upb/port/def.inc"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define kUpb_WireFormat_DefaultDepthLimit 100
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // UPB_WIRE_COMMON_H_
diff --git a/upb/wire/decode.c b/upb/wire/decode.c
index ed2ee98..c2ab7e0 100644
--- a/upb/wire/decode.c
+++ b/upb/wire/decode.c
@@ -35,6 +35,7 @@
#include "upb/mini_table/common.h"
#include "upb/mini_table/enum_internal.h"
#include "upb/port/atomic.h"
+#include "upb/wire/common.h"
#include "upb/wire/common_internal.h"
#include "upb/wire/decode_internal.h"
#include "upb/wire/encode.h"
@@ -1301,7 +1302,7 @@
decoder.extreg = extreg;
decoder.unknown = NULL;
- decoder.depth = depth ? depth : 64;
+ decoder.depth = depth ? depth : kUpb_WireFormat_DefaultDepthLimit;
decoder.end_group = DECODE_NOGROUP;
decoder.options = (uint16_t)options;
decoder.missing_required = false;
diff --git a/upb/wire/decode.h b/upb/wire/decode.h
index 95c831e..b2198f9 100644
--- a/upb/wire/decode.h
+++ b/upb/wire/decode.h
@@ -66,13 +66,19 @@
kUpb_DecodeOption_CheckRequired = 2,
};
-#define UPB_DECODE_MAXDEPTH(depth) ((depth) << 16)
+UPB_INLINE uint32_t upb_DecodeOptions_MaxDepth(uint16_t depth) {
+ return (uint32_t)depth << 16;
+}
+
+UPB_INLINE uint16_t upb_DecodeOptions_GetMaxDepth(uint32_t options) {
+ return options >> 16;
+}
// Enforce an upper bound on recursion depth.
UPB_INLINE int upb_Decode_LimitDepth(uint32_t decode_options, uint32_t limit) {
- uint32_t max_depth = decode_options >> 16;
+ uint32_t max_depth = upb_DecodeOptions_GetMaxDepth(decode_options);
if (max_depth > limit) max_depth = limit;
- return (max_depth << 16) | (decode_options & 0xffff);
+ return upb_DecodeOptions_MaxDepth(max_depth) | (decode_options & 0xffff);
}
typedef enum {
diff --git a/upb/wire/encode.c b/upb/wire/encode.c
index ef3b4ad..ef931a7 100644
--- a/upb/wire/encode.c
+++ b/upb/wire/encode.c
@@ -35,6 +35,7 @@
#include "upb/collections/map_sorter_internal.h"
#include "upb/message/extension_internal.h"
#include "upb/mini_table/sub_internal.h"
+#include "upb/wire/common.h"
#include "upb/wire/common_internal.h"
#include "upb/wire/swap_internal.h"
#include "upb/wire/types.h"
@@ -622,7 +623,7 @@
e.buf = NULL;
e.limit = NULL;
e.ptr = NULL;
- e.depth = depth ? depth : 64;
+ e.depth = depth ? depth : kUpb_WireFormat_DefaultDepthLimit;
e.options = options;
_upb_mapsorter_init(&e.sorter);