Prevent reading past end of OLS hardware buffer.

This commit is contained in:
Gareth McMullin 2011-10-29 15:21:16 +13:00 committed by Uwe Hermann
parent 9a75102313
commit 221304219e
2 changed files with 35 additions and 19 deletions

View File

@ -592,6 +592,9 @@ static int hw_set_configuration(int device_index, int capability, void *value)
tmp_u64 = value; tmp_u64 = value;
if (*tmp_u64 < MIN_NUM_SAMPLES) if (*tmp_u64 < MIN_NUM_SAMPLES)
return SR_ERR; return SR_ERR;
if (*tmp_u64 > ols->max_samples)
sr_warn("ols: sample limit exceeds hw max");
ols->limit_samples = *tmp_u64; ols->limit_samples = *tmp_u64;
sr_info("ols: sample limit %" PRIu64, ols->limit_samples); sr_info("ols: sample limit %" PRIu64, ols->limit_samples);
ret = SR_OK; ret = SR_OK;
@ -706,6 +709,7 @@ static int receive_data(int fd, int revents, void *session_data)
/* No compression. */ /* No compression. */
buffer = ols->sample; buffer = ols->sample;
buflen = 4; buflen = 4;
ols->num_samples++;
} }
if (num_channels < 4) { if (num_channels < 4) {
@ -767,7 +771,8 @@ static int receive_data(int fd, int revents, void *session_data)
packet.payload = &logic; packet.payload = &logic;
logic.length = ols->trigger_at * 4; logic.length = ols->trigger_at * 4;
logic.unitsize = 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); 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 */ /* send post-trigger samples */
packet.type = SR_DF_LOGIC; packet.type = SR_DF_LOGIC;
packet.timeoffset = ols->trigger_at * ols->period_ps; 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; 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.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); sr_session_bus(session_data, &packet);
} else { } else {
/* no trigger was used */ /* no trigger was used */
packet.type = SR_DF_LOGIC; packet.type = SR_DF_LOGIC;
packet.timeoffset = 0; packet.timeoffset = 0;
packet.duration = ols->limit_samples * ols->period_ps; packet.duration = ols->num_samples * ols->period_ps;
packet.payload = &logic; packet.payload = &logic;
logic.length = ols->limit_samples * 4; logic.length = ols->num_samples * 4;
logic.unitsize = 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); sr_session_bus(session_data, &packet);
} }
g_free(ols->raw_sample_buf); 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_flush(fd);
serial_close(fd); serial_close(fd);
packet.type = SR_DF_END; packet.type = SR_DF_END;
packet.timeoffset = ols->limit_samples * ols->period_ps; packet.timeoffset = ols->num_samples * ols->period_ps;
packet.duration = 0; packet.duration = 0;
sr_session_bus(session_data, &packet); sr_session_bus(session_data, &packet);
} }
@ -820,6 +827,7 @@ static int hw_start_acquisition(int device_index, gpointer session_data)
uint32_t data; uint32_t data;
uint16_t readcount, delaycount; uint16_t readcount, delaycount;
uint8_t changrp_mask; uint8_t changrp_mask;
int num_channels;
int i; int i;
if (!(sdi = sr_get_device_instance(device_instances, device_index))) 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) if (sdi->status != SR_ST_ACTIVE)
return SR_ERR; 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); memset(trigger_config, 0, 16);
trigger_config[ols->num_stages - 1] |= 0x08; 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) if (send_longcommand(sdi->serial->fd, CMD_CAPTURE_SIZE, reverse16(data)) != SR_OK)
return SR_ERR; 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". */ /* The flag register wants them here, and 1 means "disable channel". */
ols->flag_reg |= ~(changrp_mask << 2) & 0x3c; ols->flag_reg |= ~(changrp_mask << 2) & 0x3c;
ols->flag_reg |= FLAG_FILTER; ols->flag_reg |= FLAG_FILTER;

View File

@ -82,6 +82,7 @@ struct ols_device {
int num_stages; int num_stages;
unsigned int num_transfers; unsigned int num_transfers;
unsigned int num_samples;
int num_bytes; int num_bytes;
char last_sample[4]; char last_sample[4];
unsigned char sample[4]; unsigned char sample[4];