Skip to content

Commit b79ebf9

Browse files
Refs #22202. Apply suggestions
Signed-off-by: Juan Lopez Fernandez <juanlopez@eprosima.com>
1 parent f390a4f commit b79ebf9

3 files changed

Lines changed: 212 additions & 12 deletions

File tree

src/cpp/fastdds/xtypes/serializers/json/dynamic_data_json.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -436,8 +436,8 @@ ReturnCode_t json_serialize_basic_member(
436436
std::string utf8_value("\0", 1);
437437
#if defined(MINGW_COMPILER)
438438
// WARNING: it is the user responsibility to set the appropriate UTF-8 locale before calling this method
439-
int size_needed = std::wcstombs(nullptr, aux_wstring_value.c_str(), 0);
440-
if (size_needed < 0)
439+
size_t size_needed = std::wcstombs(nullptr, aux_wstring_value.c_str(), 0);
440+
if (size_needed == static_cast<size_t>(-1))
441441
{
442442
EPROSIMA_LOG_ERROR(XTYPES_UTILS,
443443
"Error encountered while serializing TK_CHAR16 member to JSON: encountered invalid character.");
@@ -499,8 +499,8 @@ ReturnCode_t json_serialize_basic_member(
499499
std::string utf8_value;
500500
#ifdef MINGW_COMPILER
501501
// WARNING: it is the user responsibility to set the appropriate UTF-8 locale before calling this method
502-
int size_needed = std::wcstombs(nullptr, value.c_str(), 0);
503-
if (size_needed < 0)
502+
size_t size_needed = std::wcstombs(nullptr, value.c_str(), 0);
503+
if (size_needed == static_cast<size_t>(-1))
504504
{
505505
EPROSIMA_LOG_ERROR(XTYPES_UTILS,
506506
"Error encountered while serializing TK_STRING16 member to JSON: encountered invalid character.");

src/cpp/fastdds/xtypes/serializers/json/json_dynamic_data.cpp

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -253,10 +253,7 @@ ReturnCode_t json_deserialize_basic_member(
253253
const auto value = numeric_get<uint8_t>(j);
254254
if (value != 0 && value != 1)
255255
{
256-
EPROSIMA_LOG_ERROR(XTYPES_UTILS,
257-
"Error encountered while deserializing TK_BOOLEAN member: expected 0 or 1, got " <<
258-
value);
259-
return RETCODE_BAD_PARAMETER;
256+
throw std::invalid_argument(std::string{"Expected 0 or 1, got "} + std::to_string(value));
260257
}
261258
ret = data->set_boolean_value(member_id, value);
262259
}
@@ -515,8 +512,8 @@ ReturnCode_t json_deserialize_basic_member(
515512
std::wstring aux_wstring({L'\0'});
516513
#if defined(MINGW_COMPILER)
517514
// WARNING: it is the user responsibility to set the appropriate UTF-8 locale before calling this method
518-
int size_needed = std::mbstowcs(nullptr, j_string.c_str(), 0);
519-
if (size_needed < 0)
515+
size_t size_needed = std::mbstowcs(nullptr, j_string.c_str(), 0);
516+
if (size_needed == static_cast<size_t>(-1))
520517
{
521518
EPROSIMA_LOG_ERROR(XTYPES_UTILS,
522519
"Error encountered while deserializing TK_CHAR16 member: invalid UTF-8 string.");
@@ -590,8 +587,8 @@ ReturnCode_t json_deserialize_basic_member(
590587
std::wstring value;
591588
#if defined(MINGW_COMPILER)
592589
// WARNING: it is the user responsibility to set the appropriate UTF-8 locale before calling this method
593-
int size_needed = std::mbstowcs(nullptr, j_string.c_str(), 0);
594-
if (size_needed < 0)
590+
size_t size_needed = std::mbstowcs(nullptr, j_string.c_str(), 0);
591+
if (size_needed == static_cast<size_t>(-1))
595592
{
596593
EPROSIMA_LOG_ERROR(XTYPES_UTILS,
597594
"Error encountered while deserializing TK_STRING16 member: invalid UTF-8 string.");

test/unittest/dds/xtypes/serializers/json/DynDataJSONTests.cpp

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
#include <fastdds/dds/core/ReturnCode.hpp>
2020
#include <fastdds/dds/xtypes/dynamic_types/DynamicData.hpp>
2121
#include <fastdds/dds/xtypes/dynamic_types/DynamicType.hpp>
22+
#include <fastdds/dds/xtypes/dynamic_types/DynamicTypeBuilder.hpp>
23+
#include <fastdds/dds/xtypes/dynamic_types/DynamicTypeBuilderFactory.hpp>
24+
#include <fastdds/dds/xtypes/dynamic_types/MemberDescriptor.hpp>
25+
#include <fastdds/dds/xtypes/dynamic_types/TypeDescriptor.hpp>
2226
#include <fastdds/dds/xtypes/type_representation/detail/dds_xtypes_typeobject.hpp>
2327
#include <fastdds/dds/xtypes/utils.hpp>
2428

@@ -90,6 +94,205 @@ TEST(DynDataJSONTests, ComprehensiveType)
9094
test_generic<DataTypeKind::COMPREHENSIVE_TYPE>();
9195
}
9296

97+
template<typename AddMembersFn>
98+
DynamicType::_ref_type create_struct_type(
99+
const std::string& name,
100+
AddMembersFn&& add_members)
101+
{
102+
TypeDescriptor::_ref_type type_descriptor {traits<TypeDescriptor>::make_shared()};
103+
type_descriptor->kind(TK_STRUCTURE);
104+
type_descriptor->name(name);
105+
DynamicTypeBuilder::_ref_type builder {DynamicTypeBuilderFactory::get_instance()->create_type(type_descriptor)};
106+
add_members(builder);
107+
108+
return builder->build();
109+
}
110+
111+
void test_negative_case(
112+
const std::string& json,
113+
const DynamicType::_ref_type& dyn_type)
114+
{
115+
DynamicData::_ref_type dyn_data;
116+
ReturnCode_t ret = json_deserialize(json, dyn_type, DynamicDataJsonFormat::OMG, dyn_data);
117+
118+
EXPECT_NE(ret, RETCODE_OK);
119+
EXPECT_EQ(dyn_data, nullptr); // nothing was allocated
120+
}
121+
122+
TEST(DynDataJSONTests, json_deserialize_negative)
123+
{
124+
// Malformed JSON (missing brace)
125+
{
126+
std::string json = R"({"my_bool":true)"; // malformed
127+
128+
auto dyn_type = create_struct_type("TestStruct",
129+
[](auto& b)
130+
{
131+
MemberDescriptor::_ref_type member_descriptor {traits<MemberDescriptor>::make_shared()};
132+
member_descriptor->name("my_bool");
133+
member_descriptor->type(DynamicTypeBuilderFactory::get_instance()->get_primitive_type(
134+
TK_BOOLEAN));
135+
b->add_member(member_descriptor);
136+
});
137+
138+
ASSERT_NE(dyn_type, nullptr);
139+
test_negative_case(json, dyn_type);
140+
}
141+
142+
// Numeric overflow
143+
{
144+
std::string json = R"({"my_long":8589934592})"; // Overflowing int32_t
145+
146+
auto dyn_type = create_struct_type("TestStruct",
147+
[](auto& b)
148+
{
149+
MemberDescriptor::_ref_type member_descriptor {traits<MemberDescriptor>::make_shared()};
150+
member_descriptor->name("my_long");
151+
member_descriptor->type(DynamicTypeBuilderFactory::get_instance()->get_primitive_type(
152+
TK_INT32));
153+
b->add_member(member_descriptor);
154+
});
155+
156+
ASSERT_NE(dyn_type, nullptr);
157+
test_negative_case(json, dyn_type);
158+
}
159+
160+
// Array overflow
161+
{
162+
std::string json = R"({"my_array":[1,2,3,4]})"; // Overflowing array of size 3
163+
164+
auto dyn_type = create_struct_type("TestStruct",
165+
[](auto& b)
166+
{
167+
MemberDescriptor::_ref_type array_member_descriptor {traits<MemberDescriptor>::make_shared()};
168+
array_member_descriptor->name("my_array");
169+
array_member_descriptor->type(DynamicTypeBuilderFactory::get_instance()->create_array_type(
170+
DynamicTypeBuilderFactory::get_instance()->get_primitive_type(TK_INT32), {3})->build());
171+
b->add_member(array_member_descriptor);
172+
});
173+
174+
ASSERT_NE(dyn_type, nullptr);
175+
test_negative_case(json, dyn_type);
176+
}
177+
178+
// Missing struct member
179+
{
180+
std::string json = R"({"first_attr":42})"; // "second_attr" is absent
181+
182+
auto dyn_type = create_struct_type("TestStruct",
183+
[](auto& b)
184+
{
185+
MemberDescriptor::_ref_type member_descriptor {traits<MemberDescriptor>::make_shared()};
186+
member_descriptor->name("first_attr");
187+
member_descriptor->type(DynamicTypeBuilderFactory::get_instance()->get_primitive_type(
188+
TK_INT32));
189+
b->add_member(member_descriptor);
190+
member_descriptor = traits<MemberDescriptor>::make_shared();
191+
member_descriptor->name("second_attr");
192+
member_descriptor->type(DynamicTypeBuilderFactory::get_instance()->get_primitive_type(
193+
TK_BOOLEAN));
194+
b->add_member(member_descriptor);
195+
});
196+
197+
ASSERT_NE(dyn_type, nullptr);
198+
test_negative_case(json, dyn_type);
199+
}
200+
201+
// Unknown member
202+
{
203+
std::string json = R"({"value":10,"intruder":99})"; // "intruder" is not defined in the struct
204+
205+
auto dyn_type = create_struct_type("TestStruct",
206+
[](auto& b)
207+
{
208+
MemberDescriptor::_ref_type member_descriptor {traits<MemberDescriptor>::make_shared()};
209+
member_descriptor->name("value");
210+
member_descriptor->type(DynamicTypeBuilderFactory::get_instance()->get_primitive_type(
211+
TK_INT32));
212+
b->add_member(member_descriptor);
213+
});
214+
215+
ASSERT_NE(dyn_type, nullptr);
216+
test_negative_case(json, dyn_type);
217+
}
218+
219+
// Bounded string overflow
220+
{
221+
std::string json = R"({"my_bounded_str":")" + std::string(65, 'X') + R"("})"; // 65 > bound 64
222+
223+
auto dyn_type = create_struct_type("TestStruct",
224+
[](auto& b)
225+
{
226+
MemberDescriptor::_ref_type member_descriptor {traits<MemberDescriptor>::make_shared()};
227+
member_descriptor->name("my_bounded_str");
228+
member_descriptor->type(DynamicTypeBuilderFactory::get_instance()->create_string_type(64)->
229+
build());
230+
b->add_member(member_descriptor);
231+
});
232+
233+
ASSERT_NE(dyn_type, nullptr);
234+
test_negative_case(json, dyn_type);
235+
}
236+
237+
// Invalid enum value
238+
{
239+
std::string json = R"({"color":"BLUE"})"; // "BLUE" is not a valid enum value
240+
241+
auto dyn_type = create_struct_type("TestStruct",
242+
[](auto& b)
243+
{
244+
// Define enum type
245+
TypeDescriptor::_ref_type enum_type_descriptor {traits<TypeDescriptor>::make_shared()};
246+
enum_type_descriptor->kind(TK_ENUM);
247+
enum_type_descriptor->name("MyEnum");
248+
DynamicTypeBuilder::_ref_type enum_builder {DynamicTypeBuilderFactory::get_instance()->create_type(
249+
enum_type_descriptor)};
250+
251+
// Add enum literals to the type
252+
MemberDescriptor::_ref_type enum_member_descriptor {traits<MemberDescriptor>::make_shared()};
253+
enum_member_descriptor->type(DynamicTypeBuilderFactory::get_instance()->get_primitive_type(
254+
TK_INT32));
255+
enum_member_descriptor->name("RED");
256+
enum_builder->add_member(enum_member_descriptor);
257+
enum_member_descriptor = traits<MemberDescriptor>::make_shared();
258+
enum_member_descriptor->type(DynamicTypeBuilderFactory::get_instance()->get_primitive_type(
259+
TK_INT32));
260+
enum_member_descriptor->name("GREEN");
261+
enum_builder->add_member(enum_member_descriptor);
262+
263+
// Build enum type
264+
DynamicType::_ref_type enum_type = enum_builder->build();
265+
266+
// Add enum member to the struct
267+
MemberDescriptor::_ref_type member_descriptor {traits<MemberDescriptor>::make_shared()};
268+
member_descriptor->name("color");
269+
member_descriptor->type(enum_type);
270+
b->add_member(member_descriptor);
271+
});
272+
273+
ASSERT_NE(dyn_type, nullptr);
274+
test_negative_case(json, dyn_type);
275+
}
276+
277+
// Type mismatch
278+
{
279+
std::string json = R"({"id":"not_an_int"})"; // expecting int, got string
280+
281+
auto dyn_type = create_struct_type("TestStruct",
282+
[](auto& b)
283+
{
284+
MemberDescriptor::_ref_type member_descriptor {traits<MemberDescriptor>::make_shared()};
285+
member_descriptor->name("id");
286+
member_descriptor->type(DynamicTypeBuilderFactory::get_instance()->get_primitive_type(
287+
TK_INT32));
288+
b->add_member(member_descriptor);
289+
});
290+
291+
ASSERT_NE(dyn_type, nullptr);
292+
test_negative_case(json, dyn_type);
293+
}
294+
}
295+
93296
int main(
94297
int argc,
95298
char** argv)

0 commit comments

Comments
 (0)