diff --git a/libqcdm/src/commands.c b/libqcdm/src/commands.c index b78c26b7..f182016d 100644 --- a/libqcdm/src/commands.c +++ b/libqcdm/src/commands.c @@ -672,12 +672,24 @@ qcdm_cmd_pilot_sets_result (const char *buf, size_t len, int *out_error) QcdmResult *result = NULL; DMCmdPilotSetsRsp *rsp = (DMCmdPilotSetsRsp *) buf; size_t sets_len; + size_t total_count; qcdm_return_val_if_fail (buf != NULL, NULL); if (!check_command (buf, len, DIAG_CMD_PILOT_SETS, sizeof (DMCmdPilotSetsRsp), out_error)) return NULL; + /* Validate that the modem-supplied counts fit in the fixed sets[] array + * and in the actually-received response. */ + total_count = (size_t) rsp->active_count + rsp->candidate_count + rsp->neighbor_count; + if (total_count > (sizeof (rsp->sets) / sizeof (rsp->sets[0])) || + ((sizeof (*rsp) - sizeof (rsp->sets)) + total_count * sizeof (DMCmdPilotSetsSet)) > len) { + qcdm_err (0, "DM Pilot Sets response counts out of range"); + if (out_error) + *out_error = -QCDM_ERROR_RESPONSE_BAD_LENGTH; + return NULL; + } + result = qcdm_result_new (); sets_len = rsp->active_count * sizeof (DMCmdPilotSetsSet); diff --git a/libqcdm/src/logs.c b/libqcdm/src/logs.c index 91152c42..090e0a4f 100644 --- a/libqcdm/src/logs.c +++ b/libqcdm/src/logs.c @@ -88,6 +88,7 @@ qcdm_log_item_evdo_pilot_sets_v2_new (const char *buf, size_t len, int *out_erro QcdmResult *result = NULL; DMLogItemEvdoPilotSetsV2 *pilot_sets; DMCmdLog *log_cmd = (DMCmdLog *) buf; + size_t avail; size_t sets_len; qcdm_return_val_if_fail (buf != NULL, NULL); @@ -97,6 +98,21 @@ qcdm_log_item_evdo_pilot_sets_v2_new (const char *buf, size_t len, int *out_erro pilot_sets = (DMLogItemEvdoPilotSetsV2 *) log_cmd->data; + /* check_log_item() guarantees len >= sizeof (DMCmdLog) + sizeof (DMLogItemEvdoPilotSetsV2), + * so 'avail' cannot underflow. */ + /* Ensure the flexible sets[] array actually contains as many entries as + * the header claims; the modem fully controls these counts. */ + avail = len - sizeof (DMCmdLog) - sizeof (DMLogItemEvdoPilotSetsV2); + sets_len = ((size_t) pilot_sets->active_count + + (size_t) pilot_sets->candidate_count + + (size_t) pilot_sets->remaining_count) + * sizeof (DMLogItemEvdoPilotSetsV2Pilot); + if (sets_len > avail) { + if (out_error) + *out_error = -QCDM_ERROR_RESPONSE_BAD_LENGTH; + return NULL; + } + result = qcdm_result_new (); sets_len = pilot_sets->active_count * sizeof (DMLogItemEvdoPilotSetsV2Pilot);