From: Gareth McMullin Date: Sat, 29 Oct 2011 02:21:16 +0000 (+1300) Subject: Prevent reading past end of OLS hardware buffer. X-Git-Tag: libsigrok-0.1.0~238 X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=221304219ef861c14a44017eb025631bbd2fa05c;p=libsigrok.git Prevent reading past end of OLS hardware buffer. --- diff --git a/hardware/openbench-logic-sniffer/ols.c b/hardware/openbench-logic-sniffer/ols.c index e7daa016..0f445a39 100644 --- a/hardware/openbench-logic-sniffer/ols.c +++ b/hardware/openbench-logic-sniffer/ols.c @@ -592,6 +592,9 @@ static int hw_set_configuration(int device_index, int capability, void *value) tmp_u64 = value; if (*tmp_u64 < MIN_NUM_SAMPLES) return SR_ERR; + if (*tmp_u64 > ols->max_samples) + sr_warn("ols: sample limit exceeds hw max"); + ols->limit_samples = *tmp_u64; sr_info("ols: sample limit %" PRIu64, ols->limit_samples); ret = SR_OK; @@ -706,6 +709,7 @@ static int receive_data(int fd, int revents, void *session_data) /* No compression. */ buffer = ols->sample; buflen = 4; + ols->num_samples++; } if (num_channels < 4) { @@ -767,7 +771,8 @@ static int receive_data(int fd, int revents, void *session_data) packet.payload = &logic; logic.length = ols->trigger_at * 4; logic.unitsize = 4; - logic.data = ols->raw_sample_buf; + logic.data = ols->raw_sample_buf + + (ols->limit_samples - ols->num_samples) * 4; sr_session_bus(session_data, &packet); } @@ -780,21 +785,23 @@ static int receive_data(int fd, int revents, void *session_data) /* send post-trigger samples */ packet.type = SR_DF_LOGIC; packet.timeoffset = ols->trigger_at * ols->period_ps; - packet.duration = (ols->limit_samples - ols->trigger_at) * ols->period_ps; + packet.duration = (ols->num_samples - ols->trigger_at) * ols->period_ps; packet.payload = &logic; - logic.length = (ols->limit_samples * 4) - (ols->trigger_at * 4); + logic.length = (ols->num_samples * 4) - (ols->trigger_at * 4); logic.unitsize = 4; - logic.data = ols->raw_sample_buf + ols->trigger_at * 4; + logic.data = ols->raw_sample_buf + ols->trigger_at * 4 + + (ols->limit_samples - ols->num_samples) * 4; sr_session_bus(session_data, &packet); } else { /* no trigger was used */ packet.type = SR_DF_LOGIC; packet.timeoffset = 0; - packet.duration = ols->limit_samples * ols->period_ps; + packet.duration = ols->num_samples * ols->period_ps; packet.payload = &logic; - logic.length = ols->limit_samples * 4; + logic.length = ols->num_samples * 4; logic.unitsize = 4; - logic.data = ols->raw_sample_buf; + logic.data = ols->raw_sample_buf + + (ols->limit_samples - ols->num_samples) * 4; sr_session_bus(session_data, &packet); } g_free(ols->raw_sample_buf); @@ -802,7 +809,7 @@ static int receive_data(int fd, int revents, void *session_data) serial_flush(fd); serial_close(fd); packet.type = SR_DF_END; - packet.timeoffset = ols->limit_samples * ols->period_ps; + packet.timeoffset = ols->num_samples * ols->period_ps; packet.duration = 0; sr_session_bus(session_data, &packet); } @@ -820,6 +827,7 @@ static int hw_start_acquisition(int device_index, gpointer session_data) uint32_t data; uint16_t readcount, delaycount; uint8_t changrp_mask; + int num_channels; int i; if (!(sdi = sr_get_device_instance(device_instances, device_index))) @@ -830,7 +838,24 @@ static int hw_start_acquisition(int device_index, gpointer session_data) if (sdi->status != SR_ST_ACTIVE) return SR_ERR; - readcount = ols->limit_samples / 4; + /* + * Enable/disable channel groups in the flag register according to the + * probe mask. Calculate this here, because num_channels is needed + * to limit readcount. + */ + changrp_mask = 0; + num_channels = 0; + for (i = 0; i < 4; i++) { + if (ols->probe_mask & (0xff << (i * 8))) { + changrp_mask |= (1 << i); + num_channels++; + } + } + + /* Limit readcount to prevent reading past the end of the hardware + * buffer. + */ + readcount = MIN(ols->max_samples / num_channels, ols->limit_samples) / 4; memset(trigger_config, 0, 16); trigger_config[ols->num_stages - 1] |= 0x08; @@ -903,16 +928,6 @@ static int hw_start_acquisition(int device_index, gpointer session_data) if (send_longcommand(sdi->serial->fd, CMD_CAPTURE_SIZE, reverse16(data)) != SR_OK) return SR_ERR; - /* - * Enable/disable channel groups in the flag register according to the - * probe mask. - */ - changrp_mask = 0; - for (i = 0; i < 4; i++) { - if (ols->probe_mask & (0xff << (i * 8))) - changrp_mask |= (1 << i); - } - /* The flag register wants them here, and 1 means "disable channel". */ ols->flag_reg |= ~(changrp_mask << 2) & 0x3c; ols->flag_reg |= FLAG_FILTER; diff --git a/hardware/openbench-logic-sniffer/ols.h b/hardware/openbench-logic-sniffer/ols.h index e6afd0e0..2cdf42c1 100644 --- a/hardware/openbench-logic-sniffer/ols.h +++ b/hardware/openbench-logic-sniffer/ols.h @@ -82,6 +82,7 @@ struct ols_device { int num_stages; unsigned int num_transfers; + unsigned int num_samples; int num_bytes; char last_sample[4]; unsigned char sample[4];