diff --git a/features/frameworks/mbed-coap/source/sn_coap_parser.c b/features/frameworks/mbed-coap/source/sn_coap_parser.c index 36ab20d8dc..1a892d6f37 100644 --- a/features/frameworks/mbed-coap/source/sn_coap_parser.c +++ b/features/frameworks/mbed-coap/source/sn_coap_parser.c @@ -310,9 +310,15 @@ static int8_t sn_coap_parser_options_parse(struct coap_s *handle, uint8_t **pack option_number = *(*packet_data_pptr + 1) + 13; (*packet_data_pptr)++; } else if (option_number == 14) { - option_number = *(*packet_data_pptr + 2); - option_number += (*(*packet_data_pptr + 1) << 8) + 269; - (*packet_data_pptr) += 2; + if (message_left >= 2){ + option_number = *(*packet_data_pptr + 2); + option_number += (*(*packet_data_pptr + 1) << 8) + 269; + (*packet_data_pptr) += 2; + } else { + /* packet_data_pptr would overflow! */ + tr_error("sn_coap_parser_options_parse - **packet_data_pptr overflow !"); + return -1; + } } /* Option number 15 reserved for payload marker. This is handled as a error! */ else if (option_number == 15) { @@ -320,6 +326,14 @@ static int8_t sn_coap_parser_options_parse(struct coap_s *handle, uint8_t **pack return -1; } + message_left = packet_len - ((*packet_data_pptr) - packet_data_start_ptr); + + if (message_left == 0){ + /* packet_data_pptr would overflow! */ + tr_error("sn_coap_parser_options_parse - **packet_data_pptr overflow !"); + return -1; + } + /* Add previous option to option delta and get option number */ option_number += previous_option_number; @@ -328,9 +342,15 @@ static int8_t sn_coap_parser_options_parse(struct coap_s *handle, uint8_t **pack option_len = *(*packet_data_pptr + 1) + 13; (*packet_data_pptr)++; } else if (option_len == 14) { - option_len = *(*packet_data_pptr + 2); - option_len += (*(*packet_data_pptr + 1) << 8) + 269; - (*packet_data_pptr) += 2; + if (message_left >= 2){ + option_len = *(*packet_data_pptr + 2); + option_len += (*(*packet_data_pptr + 1) << 8) + 269; + (*packet_data_pptr) += 2; + } else { + /* packet_data_pptr would overflow! */ + tr_error("sn_coap_parser_options_parse - **packet_data_pptr overflow while resolving option length!"); + return -1; + } } /* Option number length 15 is reserved for the future use - ERROR */ else if (option_len == 15) { @@ -340,6 +360,8 @@ static int8_t sn_coap_parser_options_parse(struct coap_s *handle, uint8_t **pack message_left = packet_len - (*packet_data_pptr - packet_data_start_ptr); + + /* * * Parse option itself * * */ /* Some options are handled independently in own functions */ previous_option_number = option_number; @@ -366,6 +388,12 @@ static int8_t sn_coap_parser_options_parse(struct coap_s *handle, uint8_t **pack break; } + if (message_left < option_len){ + /* packet_data_pptr would overflow! */ + tr_error("sn_coap_parser_options_parse - **packet_data_pptr would overflow when parsing options!"); + return -1; + } + /* Parse option */ switch (option_number) { case COAP_OPTION_CONTENT_FORMAT: @@ -400,9 +428,7 @@ static int8_t sn_coap_parser_options_parse(struct coap_s *handle, uint8_t **pack tr_error("sn_coap_parser_options_parse - COAP_OPTION_PROXY_URI allocation failed!"); return -1; } - (*packet_data_pptr) += option_len; - break; case COAP_OPTION_ETAG: @@ -581,11 +607,9 @@ static int8_t sn_coap_parser_options_parse(struct coap_s *handle, uint8_t **pack if ((*packet_data_pptr - packet_data_start_ptr) > packet_len) { return -1; } - message_left = packet_len - (*packet_data_pptr - packet_data_start_ptr); } - return 0; }