Skip to content

Commit 6165805

Browse files
LCM Validation when loading codeletset (#127)
* Add validation in lcm requests when loading codelets * Fix * Revert * Refactor and Add JBPF_MAX_CODELETS_IN_CODELETSET * Move outside the loop * Refactor * pass by const ref * Further refactor * Minor logging * Add copilot's suggestion
1 parent 2d73c23 commit 6165805

File tree

7 files changed

+139
-80
lines changed

7 files changed

+139
-80
lines changed

examples/reverse_proxy/listener.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,7 @@ handle_request(http::request<Body, http::basic_fields<Allocator>>&& req, Send&&
7878
read_json(is, pt);
7979
jbpf_codeletset_load_req load_req = {0};
8080

81-
std::vector<std::string> codeletset_elems;
82-
codeletset_elems.push_back(address);
83-
if (jbpf_reverse_proxy::parser::parse_jbpf_codeletset_load_req(pt, &load_req, codeletset_elems))
81+
if (jbpf_reverse_proxy::parser::parse_jbpf_codeletset_load_req(pt, &load_req, {address}))
8482
return send(bad_request("Invalid JSON"));
8583

8684
std::cout << "Loading codelet set: " << load_req.codeletset_id.name << std::endl;

examples/reverse_proxy/parser.cpp

Lines changed: 59 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ auto_expand_environment_variables(string& text)
3737
}
3838

3939
parse_req_outcome
40-
parse_jbpf_io_channel_desc(const ptree pt, const string path, jbpf_io_channel_desc_s* dest, vector<string> stream_elems)
40+
parse_jbpf_io_channel_desc(
41+
const ptree pt, const string path, jbpf_io_channel_desc_s* dest, const vector<string>& stream_elems)
4142
{
4243
auto name = pt.get_child("name").get_value<string>();
4344
if (name.length() > JBPF_IO_CHANNEL_NAME_LEN - 1) {
@@ -53,12 +54,8 @@ parse_jbpf_io_channel_desc(const ptree pt, const string path, jbpf_io_channel_de
5354
if (jbpf_lcm_cli::stream_id::from_hex(stream_id.value().get_value<string>(), &dest->stream_id))
5455
return JBPF_LCM_PARSE_REQ_FAILED;
5556
} else {
56-
vector<string> map_elems;
57-
58-
for (auto elem : stream_elems)
59-
map_elems.push_back(elem);
60-
61-
map_elems.push_back(name);
57+
vector<string> map_elems = stream_elems;
58+
map_elems.emplace_back(name);
6259

6360
if (jbpf_lcm_cli::stream_id::generate_from_strings(map_elems, &dest->stream_id))
6461
return JBPF_LCM_PARSE_REQ_FAILED;
@@ -112,25 +109,40 @@ parse_jbpf_linked_map_descriptor(const ptree pt, jbpf_linked_map_descriptor_s* d
112109
}
113110

114111
parse_req_outcome
115-
parse_jbpf_codelet_descriptor(const ptree pt, jbpf_codelet_descriptor_s* dest, vector<string> codelet_elems)
112+
parse_jbpf_codelet_descriptor(const ptree pt, jbpf_codelet_descriptor_s* dest, const vector<string>& codelet_elems)
116113
{
117-
auto codelet_name = pt.get_child("codelet_name").get_value<string>();
114+
auto codelet_name_opt = pt.get_child_optional("codelet_name");
115+
if (!codelet_name_opt) {
116+
cout << "Missing required field: codelet_name\n";
117+
return JBPF_LCM_PARSE_REQ_FAILED;
118+
}
119+
auto codelet_name = codelet_name_opt->get_value<string>();
118120
if (codelet_name.length() > JBPF_CODELET_NAME_LEN - 1) {
119121
cout << "codelet_descriptor[].codelet_name length must be at most " << JBPF_CODELET_NAME_LEN - 1 << endl;
120122
return JBPF_LCM_PARSE_REQ_FAILED;
121123
}
122124
codelet_name.copy(dest->codelet_name, JBPF_CODELET_NAME_LEN - 1);
123125
dest->codelet_name[codelet_name.length()] = '\0';
124126

125-
auto hook_name = pt.get_child("hook_name").get_value<string>();
127+
auto hook_name_opt = pt.get_child_optional("hook_name");
128+
if (!hook_name_opt) {
129+
cout << "Missing required field: hook_name\n";
130+
return JBPF_LCM_PARSE_REQ_FAILED;
131+
}
132+
auto hook_name = hook_name_opt->get_value<string>();
126133
if (hook_name.length() > JBPF_HOOK_NAME_LEN - 1) {
127134
cout << "codelet_descriptor[].hook_name length must be at most " << JBPF_HOOK_NAME_LEN - 1 << endl;
128135
return JBPF_LCM_PARSE_REQ_FAILED;
129136
}
130137
hook_name.copy(dest->hook_name, JBPF_HOOK_NAME_LEN - 1);
131138
dest->hook_name[hook_name.length()] = '\0';
132139

133-
auto codelet_path = pt.get_child("codelet_path").get_value<string>();
140+
auto codelet_path_opt = pt.get_child_optional("codelet_path");
141+
if (!codelet_path_opt) {
142+
cout << "Missing required field: codelet_path\n";
143+
return JBPF_LCM_PARSE_REQ_FAILED;
144+
}
145+
auto codelet_path = codelet_path_opt->get_value<string>();
134146
auto_expand_environment_variables(codelet_path);
135147
if (codelet_path.length() > JBPF_PATH_LEN - 1) {
136148
cout << "codelet_descriptor[].codelet_path length must be at most " << JBPF_PATH_LEN - 1 << endl;
@@ -159,16 +171,18 @@ parse_jbpf_codelet_descriptor(const ptree pt, jbpf_codelet_descriptor_s* dest, v
159171

160172
auto in_io_channel = pt.get_child_optional("in_io_channel");
161173
if (in_io_channel) {
174+
vector<string> stream_elements_in_io_channel = codelet_elems;
175+
stream_elements_in_io_channel.emplace_back(codelet_name);
176+
stream_elements_in_io_channel.emplace_back(hook_name);
177+
stream_elements_in_io_channel.emplace_back("input");
162178
auto idx = 0;
163179
BOOST_FOREACH (const ptree::value_type& child, in_io_channel.value()) {
164-
vector<string> stream_elems;
165-
for (auto elem : codelet_elems)
166-
stream_elems.push_back(elem);
167-
stream_elems.push_back(codelet_name);
168-
stream_elems.push_back(hook_name);
169-
stream_elems.push_back("input");
170-
auto ret =
171-
parse_jbpf_io_channel_desc(child.second, "in_io_channel", &dest->in_io_channel[idx], stream_elems);
180+
if (idx >= JBPF_MAX_IO_CHANNEL) {
181+
cout << "Too many in_io_channel entries (max " << JBPF_MAX_IO_CHANNEL << ")\n";
182+
return JBPF_LCM_PARSE_REQ_FAILED;
183+
}
184+
auto ret = parse_jbpf_io_channel_desc(
185+
child.second, "in_io_channel", &dest->in_io_channel[idx], stream_elements_in_io_channel);
172186
if (ret != JBPF_LCM_PARSE_REQ_SUCCESS)
173187
return ret;
174188
idx++;
@@ -178,16 +192,18 @@ parse_jbpf_codelet_descriptor(const ptree pt, jbpf_codelet_descriptor_s* dest, v
178192

179193
auto out_io_channel = pt.get_child_optional("out_io_channel");
180194
if (out_io_channel) {
195+
vector<string> stream_elements_out_io_channel = codelet_elems;
196+
stream_elements_out_io_channel.emplace_back(codelet_name);
197+
stream_elements_out_io_channel.emplace_back(hook_name);
198+
stream_elements_out_io_channel.emplace_back("output");
181199
auto idx = 0;
182200
BOOST_FOREACH (const ptree::value_type& child, out_io_channel.value()) {
183-
vector<string> stream_elems;
184-
for (auto elem : codelet_elems)
185-
stream_elems.push_back(elem);
186-
stream_elems.push_back(codelet_name);
187-
stream_elems.push_back(hook_name);
188-
stream_elems.push_back("output");
189-
auto ret =
190-
parse_jbpf_io_channel_desc(child.second, "out_io_channel", &dest->out_io_channel[idx], stream_elems);
201+
if (idx >= JBPF_MAX_IO_CHANNEL) {
202+
cout << "Too many out_io_channel entries (max " << JBPF_MAX_IO_CHANNEL << ")\n";
203+
return JBPF_LCM_PARSE_REQ_FAILED;
204+
}
205+
auto ret = parse_jbpf_io_channel_desc(
206+
child.second, "out_io_channel", &dest->out_io_channel[idx], stream_elements_out_io_channel);
191207
if (ret != JBPF_LCM_PARSE_REQ_SUCCESS)
192208
return ret;
193209
idx++;
@@ -198,7 +214,11 @@ parse_jbpf_codelet_descriptor(const ptree pt, jbpf_codelet_descriptor_s* dest, v
198214
auto linked_maps = pt.get_child_optional("linked_maps");
199215
if (linked_maps) {
200216
auto idx = 0;
201-
BOOST_FOREACH (const ptree::value_type& child, pt.get_child("linked_maps")) {
217+
BOOST_FOREACH (const ptree::value_type& child, linked_maps.value()) {
218+
if (idx >= JBPF_MAX_LINKED_MAPS) {
219+
cout << "Too many linked_maps entries (max " << JBPF_MAX_LINKED_MAPS << ")\n";
220+
return JBPF_LCM_PARSE_REQ_FAILED;
221+
}
202222
auto ret = parse_jbpf_linked_map_descriptor(child.second, &dest->linked_maps[idx]);
203223
if (ret != JBPF_LCM_PARSE_REQ_SUCCESS)
204224
return ret;
@@ -214,7 +234,7 @@ parse_jbpf_codelet_descriptor(const ptree pt, jbpf_codelet_descriptor_s* dest, v
214234
jbpf_verify_func_t verifier_func = NULL;
215235

216236
parse_req_outcome
217-
parse_jbpf_codeletset_load_req(const ptree pt, jbpf_codeletset_load_req* dest, vector<string> codeletset_elems)
237+
parse_jbpf_codeletset_load_req(const ptree pt, jbpf_codeletset_load_req* dest, const vector<string>& codeletset_elems)
218238
{
219239
auto name = pt.get_child("codeletset_id").get_value<string>();
220240
if (name.length() > JBPF_CODELETSET_NAME_LEN - 1) {
@@ -224,13 +244,17 @@ parse_jbpf_codeletset_load_req(const ptree pt, jbpf_codeletset_load_req* dest, v
224244
name.copy(dest->codeletset_id.name, JBPF_CODELETSET_NAME_LEN - 1);
225245
dest->codeletset_id.name[name.length()] = '\0';
226246

227-
auto idx = 0;
247+
vector<string> codelet_elems_with_name = codeletset_elems;
248+
codelet_elems_with_name.emplace_back(name);
249+
250+
int idx = 0;
228251
BOOST_FOREACH (const ptree::value_type& child, pt.get_child("codelet_descriptor")) {
229-
vector<string> codelet_elems;
230-
for (auto elem : codeletset_elems)
231-
codelet_elems.push_back(elem);
232-
codelet_elems.push_back(name);
233-
auto ret = internal::parse_jbpf_codelet_descriptor(child.second, &dest->codelet_descriptor[idx], codelet_elems);
252+
if (idx >= JBPF_MAX_CODELETS_IN_CODELETSET) {
253+
cout << "Too many codelet_descriptors (max " << JBPF_MAX_CODELETS_IN_CODELETSET << ")\n";
254+
return JBPF_LCM_PARSE_REQ_FAILED;
255+
}
256+
auto ret = internal::parse_jbpf_codelet_descriptor(
257+
child.second, &dest->codelet_descriptor[idx], codelet_elems_with_name);
234258
if (ret != JBPF_LCM_PARSE_REQ_SUCCESS)
235259
return ret;
236260
idx++;

examples/reverse_proxy/parser.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ parser_jbpf_set_verify_func(jbpf_verify_func_t func);
2424

2525
parse_req_outcome
2626
parse_jbpf_codeletset_load_req(
27-
const boost::property_tree::ptree pt, jbpf_codeletset_load_req* dest, std::vector<std::string> codeletset_elems);
27+
const boost::property_tree::ptree pt,
28+
jbpf_codeletset_load_req* dest,
29+
const std::vector<std::string>& codeletset_elems);
2830
parse_req_outcome
2931
parse_jbpf_codeletset_unload_req(const boost::property_tree::ptree pt, jbpf_codeletset_unload_req* dest);
3032
std::string

jbpf_tests/functional/request_validation/codelet_LinkedMaps_maxExceeded.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ main(int argc, char** argv)
132132

133133
// Load the codeletset
134134
assert(jbpf_codeletset_load(&codeletset_req_c1, &err_msg) == JBPF_CODELET_PARAM_INVALID);
135+
assert(strlen(err_msg.err_msg) > 0);
135136

136137
// Stop
137138
jbpf_stop();

tools/lcm_cli/loader.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,7 @@ parseArgs(int ac, char** av, lcm_cli_config* opts)
130130
jbpf_lcm_cli::parser::parse_req_outcome parse_ret;
131131
switch ((*opts).typ) {
132132
case load: {
133-
vector<string> codeletset_elems;
134-
codeletset_elems.push_back(address);
135-
parse_ret = jbpf_lcm_cli::parser::parse_jbpf_codeletset_load_req(cfg, &(*opts).req.load, codeletset_elems);
133+
parse_ret = jbpf_lcm_cli::parser::parse_jbpf_codeletset_load_req(cfg, &(*opts).req.load, {address});
136134
break;
137135
}
138136

0 commit comments

Comments
 (0)