diff --git a/drivers/mbimmodem/mbim-message.c b/drivers/mbimmodem/mbim-message.c index fd8c5f08..25cb45b6 100644 --- a/drivers/mbimmodem/mbim-message.c +++ b/drivers/mbimmodem/mbim-message.c @@ -31,6 +31,7 @@ #include "mbim-message.h" #include "mbim-private.h" +#define MAX_NESTING 2 /* a(uss) */ #define HEADER_SIZE (sizeof(struct mbim_message_header) + \ sizeof(struct mbim_fragment_header)) @@ -410,7 +411,7 @@ static bool message_iter_next_entry_valist(struct mbim_message_iter *orig, const char *end; uint32_t *out_n_elem; struct mbim_message_iter *sub_iter; - struct mbim_message_iter stack[2]; + struct mbim_message_iter stack[MAX_NESTING]; unsigned int indent = 0; void *arg; @@ -459,6 +460,9 @@ static bool message_iter_next_entry_valist(struct mbim_message_iter *orig, signature += 1; indent += 1; + if (unlikely(indent > MAX_NESTING)) + return false; + if (!_iter_enter_struct(iter, &stack[indent - 1])) return false; @@ -466,6 +470,9 @@ static bool message_iter_next_entry_valist(struct mbim_message_iter *orig, break; case ')': + if (unlikely(indent == 0)) + return false; + signature += 1; indent -= 1; @@ -719,7 +726,7 @@ struct container { size_t obuf_size; size_t obuf_pos; char container_type; - char signature[256]; + char signature[64]; uint8_t sigindex; uint32_t base_offset; uint32_t array_start; @@ -748,7 +755,7 @@ static void container_update_offsets(struct container *container) struct mbim_message_builder { struct mbim_message *message; - struct container stack[3]; + struct container stack[MAX_NESTING + 1]; uint32_t index; }; @@ -945,6 +952,9 @@ bool mbim_message_builder_enter_struct(struct mbim_message_builder *builder, { struct container *container; + if (strlen(signature) > sizeof(((struct container *) 0)->signature) - 1) + return false; + if (builder->index == L_ARRAY_SIZE(builder->stack) - 1) return false; @@ -1015,6 +1025,9 @@ bool mbim_message_builder_enter_array(struct mbim_message_builder *builder, struct container *parent; struct container *container; + if (strlen(signature) > sizeof(((struct container *) 0)->signature) - 1) + return false; + if (builder->index == L_ARRAY_SIZE(builder->stack) - 1) return false; @@ -1116,16 +1129,19 @@ static bool append_arguments(struct mbim_message *message, const char *signature, va_list args) { struct mbim_message_builder *builder; - char subsig[256]; + char subsig[64]; const char *sigend; struct { char type; const char *sig_start; const char *sig_end; unsigned int n_items; - } stack[4]; + } stack[MAX_NESTING + 1]; unsigned int stack_index = 0; + if (strlen(signature) > sizeof(subsig) - 1) + return false; + builder = mbim_message_builder_new(message); stack[stack_index].type = CONTAINER_TYPE_STRUCT; @@ -1146,6 +1162,9 @@ static bool append_arguments(struct mbim_message *message, stack[stack_index].sig_end) { bool r = false; + if (stack_index == 0) + goto error; + if (stack[stack_index].type == CONTAINER_TYPE_ARRAY) r = mbim_message_builder_leave_array(builder); if (stack[stack_index].type == CONTAINER_TYPE_STRUCT) @@ -1201,6 +1220,9 @@ static bool append_arguments(struct mbim_message *message, break; } case '(': + if (stack_index == MAX_NESTING) + goto error; + sigend = _signature_end(s); memcpy(subsig, s + 1, sigend - s - 1); subsig[sigend - s - 1] = '\0'; @@ -1220,6 +1242,9 @@ static bool append_arguments(struct mbim_message *message, break; case 'a': + if (stack_index == MAX_NESTING) + goto error; + sigend = _signature_end(s + 1) + 1; memcpy(subsig, s + 1, sigend - s - 1); subsig[sigend - s - 1] = '\0'; diff --git a/unit/test-mbim.c b/unit/test-mbim.c index 5f681fe8..cb5be3b0 100644 --- a/unit/test-mbim.c +++ b/unit/test-mbim.c @@ -368,6 +368,24 @@ static void parse_phonebook_read(const void *data) mbim_message_unref(msg); } +static void build_phonebook_read(const void *data) +{ + const struct message_data *msg_data = data; + bool r; + struct mbim_message *message; + + message = _mbim_message_new_command_done(mbim_uuid_phonebook, 2, 0); + assert(message); + + r = mbim_message_set_arguments(message, "a(uss)", 1, + 3, "921123456", "TS"); + assert(r); + + _mbim_message_set_tid(message, msg_data->tid); + assert(check_message(message, msg_data)); + mbim_message_unref(message); +} + int main(int argc, char *argv[]) { l_test_init(&argc, &argv); @@ -386,6 +404,8 @@ int main(int argc, char *argv[]) l_test_add("Phonebook Read (parse)", parse_phonebook_read, &message_data_phonebook_read); + l_test_add("Phonebook Read (build)", build_phonebook_read, + &message_data_phonebook_read); return l_test_run(); }