Skip to content

Commit d03ebf6

Browse files
Blast545ahcorde
authored andcommitted
Fix bug error handling get_param_files (#743)
* Add bomb allocator * Fix memory checked for error * Add tests for bad alloc * Fix break statement * Add static keyword to methods added Signed-off-by: Jorge Perez <[email protected]>
1 parent 25ee6ca commit d03ebf6

File tree

3 files changed

+111
-4
lines changed

3 files changed

+111
-4
lines changed

rcl/src/rcl/arguments.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,7 @@ rcl_arguments_get_param_files(
9393
if (NULL == (*parameter_files)[i]) {
9494
// deallocate allocated memory
9595
for (int r = i; r >= 0; --r) {
96-
if (NULL == (*parameter_files[r])) {
97-
break;
98-
}
99-
allocator.deallocate((*parameter_files[r]), allocator.state);
96+
allocator.deallocate((*parameter_files)[r], allocator.state);
10097
}
10198
allocator.deallocate((*parameter_files), allocator.state);
10299
(*parameter_files) = NULL;

rcl/test/rcl/allocator_testing_utils.h

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,80 @@ set_failing_allocator_is_failing(rcutils_allocator_t & failing_allocator, bool s
8787
((__failing_allocator_state *)failing_allocator.state)->is_failing = state;
8888
}
8989

90+
typedef struct time_bomb_allocator_state
91+
{
92+
int count_until_failure;
93+
} time_bomb_allocator_state;
94+
95+
static void * time_bomb_malloc(size_t size, void * state)
96+
{
97+
time_bomb_allocator_state * time_bomb_state = (time_bomb_allocator_state *)state;
98+
if (time_bomb_state->count_until_failure >= 0 &&
99+
time_bomb_state->count_until_failure-- == 0)
100+
{
101+
return nullptr;
102+
}
103+
return rcutils_get_default_allocator().allocate(size, rcutils_get_default_allocator().state);
104+
}
105+
106+
static void *
107+
time_bomb_realloc(void * pointer, size_t size, void * state)
108+
{
109+
time_bomb_allocator_state * time_bomb_state = (time_bomb_allocator_state *)state;
110+
if (time_bomb_state->count_until_failure >= 0 &&
111+
time_bomb_state->count_until_failure-- == 0)
112+
{
113+
return nullptr;
114+
}
115+
return rcutils_get_default_allocator().reallocate(
116+
pointer, size, rcutils_get_default_allocator().state);
117+
}
118+
119+
static void
120+
time_bomb_free(void * pointer, void * state)
121+
{
122+
time_bomb_allocator_state * time_bomb_state = (time_bomb_allocator_state *)state;
123+
if (time_bomb_state->count_until_failure >= 0 &&
124+
time_bomb_state->count_until_failure-- == 0)
125+
{
126+
return;
127+
}
128+
rcutils_get_default_allocator().deallocate(pointer, rcutils_get_default_allocator().state);
129+
}
130+
131+
static void *
132+
time_bomb_calloc(size_t number_of_elements, size_t size_of_element, void * state)
133+
{
134+
time_bomb_allocator_state * time_bomb_state = (time_bomb_allocator_state *)state;
135+
if (time_bomb_state->count_until_failure >= 0 &&
136+
time_bomb_state->count_until_failure-- == 0)
137+
{
138+
return nullptr;
139+
}
140+
return rcutils_get_default_allocator().zero_allocate(
141+
number_of_elements, size_of_element, rcutils_get_default_allocator().state);
142+
}
143+
144+
static inline rcutils_allocator_t
145+
get_time_bombed_allocator(void)
146+
{
147+
static time_bomb_allocator_state state;
148+
state.count_until_failure = 1;
149+
auto time_bombed_allocator = rcutils_get_default_allocator();
150+
time_bombed_allocator.allocate = time_bomb_malloc;
151+
time_bombed_allocator.deallocate = time_bomb_free;
152+
time_bombed_allocator.reallocate = time_bomb_realloc;
153+
time_bombed_allocator.zero_allocate = time_bomb_calloc;
154+
time_bombed_allocator.state = &state;
155+
return time_bombed_allocator;
156+
}
157+
158+
static inline void
159+
set_time_bombed_allocator_count(rcutils_allocator_t & time_bombed_allocator, int count)
160+
{
161+
((time_bomb_allocator_state *)time_bombed_allocator.state)->count_until_failure = count;
162+
}
163+
90164
#ifdef __cplusplus
91165
}
92166
#endif

rcl/test/rcl/test_arguments.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,3 +1029,39 @@ TEST_F(CLASSNAME(TestArgumentsFixture, RMW_IMPLEMENTATION), test_param_overrides
10291029
ASSERT_TRUE(NULL != param_value->string_value);
10301030
EXPECT_STREQ("foo", param_value->string_value);
10311031
}
1032+
1033+
TEST_F(CLASSNAME(TestArgumentsFixture, RMW_IMPLEMENTATION), test_bad_alloc_get_param_files) {
1034+
const std::string parameters_filepath1 = (test_path / "test_parameters.1.yaml").string();
1035+
const std::string parameters_filepath2 = (test_path / "test_parameters.2.yaml").string();
1036+
const char * const argv[] = {
1037+
"process_name", "--ros-args", "--params-file", parameters_filepath1.c_str(),
1038+
"-r", "__ns:=/namespace", "random:=arg", "--params-file", parameters_filepath2.c_str()
1039+
};
1040+
const int argc = sizeof(argv) / sizeof(const char *);
1041+
1042+
rcl_arguments_t parsed_args = rcl_get_zero_initialized_arguments();
1043+
rcl_ret_t ret = rcl_parse_arguments(argc, argv, rcl_get_default_allocator(), &parsed_args);
1044+
ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
1045+
OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT(
1046+
{
1047+
EXPECT_EQ(RCL_RET_OK, rcl_arguments_fini(&parsed_args));
1048+
});
1049+
1050+
int parameter_filecount = rcl_arguments_get_param_files_count(&parsed_args);
1051+
EXPECT_EQ(2, parameter_filecount);
1052+
1053+
// Configure allocator to fail at different points of the code
1054+
rcl_allocator_t bomb_alloc = get_time_bombed_allocator();
1055+
set_time_bombed_allocator_count(bomb_alloc, 0);
1056+
char ** parameter_files = NULL;
1057+
ret = rcl_arguments_get_param_files(&parsed_args, bomb_alloc, &parameter_files);
1058+
EXPECT_EQ(RCL_RET_BAD_ALLOC, ret) << rcl_get_error_string().str;
1059+
1060+
set_time_bombed_allocator_count(bomb_alloc, 1);
1061+
ret = rcl_arguments_get_param_files(&parsed_args, bomb_alloc, &parameter_files);
1062+
EXPECT_EQ(RCL_RET_BAD_ALLOC, ret) << rcl_get_error_string().str;
1063+
1064+
set_time_bombed_allocator_count(bomb_alloc, 2);
1065+
ret = rcl_arguments_get_param_files(&parsed_args, bomb_alloc, &parameter_files);
1066+
EXPECT_EQ(RCL_RET_BAD_ALLOC, ret) << rcl_get_error_string().str;
1067+
}

0 commit comments

Comments
 (0)