aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2024-03-31 20:04:41 +0200
committerPaolo Bonzini <pbonzini@redhat.com>2024-04-02 18:08:59 +0200
commite497e6a55786a62ffe009a3fe2fa6d40e6080210 (patch)
tree63d9a35821dfdfaa5ce4d3ca25f5a6d2a50ba61b
parent1d1ee7e0a1b7041804e8c5f8c2453fdc2df0407e (diff)
downloadqemu-e497e6a55786a62ffe009a3fe2fa6d40e6080210.zip
qemu-e497e6a55786a62ffe009a3fe2fa6d40e6080210.tar.gz
qemu-e497e6a55786a62ffe009a3fe2fa6d40e6080210.tar.bz2
lsi53c895a: avoid out of bounds access to s->msg[]
If no bytes are there to process in the message in phase, the input data latch (s->sidl) is set to s->msg[-1]. Just do nothing since no DMA is performed. Reported-by: Chuhong Yuan <hslester96@gmail.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--hw/scsi/lsi53c895a.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c
index 71f759a..eb9828d 100644
--- a/hw/scsi/lsi53c895a.c
+++ b/hw/scsi/lsi53c895a.c
@@ -927,13 +927,18 @@ static void lsi_do_msgin(LSIState *s)
assert(len > 0 && len <= LSI_MAX_MSGIN_LEN);
if (len > s->dbc)
len = s->dbc;
- pci_dma_write(PCI_DEVICE(s), s->dnad, s->msg, len);
- /* Linux drivers rely on the last byte being in the SIDL. */
- s->sidl = s->msg[len - 1];
- s->msg_len -= len;
- if (s->msg_len) {
- memmove(s->msg, s->msg + len, s->msg_len);
- } else {
+
+ if (len) {
+ pci_dma_write(PCI_DEVICE(s), s->dnad, s->msg, len);
+ /* Linux drivers rely on the last byte being in the SIDL. */
+ s->sidl = s->msg[len - 1];
+ s->msg_len -= len;
+ if (s->msg_len) {
+ memmove(s->msg, s->msg + len, s->msg_len);
+ }
+ }
+
+ if (!s->msg_len) {
/* ??? Check if ATN (not yet implemented) is asserted and maybe
switch to PHASE_MO. */
switch (s->msg_action) {