diff --git a/subsys/modem/modem_cmux.c b/subsys/modem/modem_cmux.c index 4a755284bff..7a78b06a8f3 100644 --- a/subsys/modem/modem_cmux.c +++ b/subsys/modem/modem_cmux.c @@ -816,6 +816,14 @@ static void modem_cmux_process_received_byte(struct modem_cmux *cmux, uint8_t by /* Get last 8 bits of data length */ cmux->frame.data_len |= ((uint16_t)byte) << 7; + if (cmux->frame.data_len > cmux->receive_buf_size) { + LOG_ERR("Indicated frame data length %u exceeds receive buffer size %u", + cmux->frame.data_len, cmux->receive_buf_size); + + cmux->receive_state = MODEM_CMUX_RECEIVE_STATE_DROP; + break; + } + /* Await data */ cmux->receive_state = MODEM_CMUX_RECEIVE_STATE_DATA; break; diff --git a/tests/subsys/modem/modem_cmux/src/main.c b/tests/subsys/modem/modem_cmux/src/main.c index 28d772614b1..579dbb8635e 100644 --- a/tests/subsys/modem/modem_cmux/src/main.c +++ b/tests/subsys/modem/modem_cmux/src/main.c @@ -148,6 +148,14 @@ static uint8_t cmux_frame_dlci2_at_newline[] = {0xF9, 0x0B, 0xEF, 0x05, 0x0D, 0x static uint8_t cmux_frame_data_dlci2_at_newline[] = {0x0D, 0x0A}; +/*************************************************************************************************/ +/* DLCI2 AT CMUX error frames */ +/*************************************************************************************************/ +static uint8_t cmux_frame_dlci2_at_cgdcont_invalid_length[] = { + 0xF9, 0x0B, 0xEF, 0xFE, 0x41, 0x54, 0x2B, 0x43, 0x47, 0x44, 0x43, 0x4F, 0x4E, + 0x54, 0x3D, 0x31, 0x2C, 0x22, 0x49, 0x50, 0x22, 0x2C, 0x22, 0x74, 0x72, 0x61, + 0x63, 0x6B, 0x75, 0x6E, 0x69, 0x74, 0x2E, 0x6D, 0x32, 0x6D, 0x22, 0x23, 0xF9}; + /*************************************************************************************************/ /* DLCI1 AT CMUX frames */ /*************************************************************************************************/ @@ -814,4 +822,46 @@ ZTEST(modem_cmux, test_modem_cmux_prevent_work_while_released) zassert_ok(modem_pipe_open(dlci2_pipe, K_SECONDS(10))); } +ZTEST(modem_cmux, test_modem_drop_frames_with_invalid_length) +{ + int ret; + uint32_t events; + + modem_backend_mock_put(&bus_mock, cmux_frame_dlci2_at_cgdcont_invalid_length, + sizeof(cmux_frame_dlci2_at_cgdcont_invalid_length)); + + k_msleep(100); + + events = k_event_test(&cmux_event, EVENT_CMUX_DLCI2_RECEIVE_READY); + + zassert_false(events & EVENT_CMUX_DLCI2_RECEIVE_READY, + "Receive event should not have been received for DLCI2 pipe"); + + modem_backend_mock_put(&bus_mock, cmux_frame_dlci2_at_cgdcont, + sizeof(cmux_frame_dlci2_at_cgdcont)); + + modem_backend_mock_put(&bus_mock, cmux_frame_dlci2_at_newline, + sizeof(cmux_frame_dlci2_at_newline)); + + k_msleep(100); + + events = k_event_test(&cmux_event, EVENT_CMUX_DLCI2_RECEIVE_READY); + zassert_equal(events, EVENT_CMUX_DLCI2_RECEIVE_READY, + "Receive ready event not received for DLCI2 pipe"); + + ret = modem_pipe_receive(dlci2_pipe, buffer2, sizeof(buffer2)); + zassert_true(ret == (sizeof(cmux_frame_data_dlci2_at_cgdcont) + + sizeof(cmux_frame_data_dlci2_at_newline)), + "Incorrect number of bytes received"); + + zassert_true(memcmp(buffer2, cmux_frame_data_dlci2_at_cgdcont, + sizeof(cmux_frame_data_dlci2_at_cgdcont)) == 0, + "Incorrect data received"); + + zassert_true(memcmp(&buffer2[sizeof(cmux_frame_data_dlci2_at_cgdcont)], + cmux_frame_data_dlci2_at_newline, + sizeof(cmux_frame_data_dlci2_at_newline)) == 0, + "Incorrect data received"); +} + ZTEST_SUITE(modem_cmux, NULL, test_modem_cmux_setup, test_modem_cmux_before, NULL, NULL);