summaryrefslogtreecommitdiffstats
path: root/semihosting
diff options
context:
space:
mode:
authorRichard Henderson2022-04-29 21:15:14 +0200
committerRichard Henderson2022-06-28 01:05:52 +0200
commit40f1219a8b2f95808ed5a18798dbce1b57fef211 (patch)
treec4838d2783f9be34e280708c2153f31fc94993d2 /semihosting
parentsemihosting: Split out semihost_sys_write (diff)
downloadqemu-40f1219a8b2f95808ed5a18798dbce1b57fef211.tar.gz
qemu-40f1219a8b2f95808ed5a18798dbce1b57fef211.tar.xz
qemu-40f1219a8b2f95808ed5a18798dbce1b57fef211.zip
semihosting: Bound length for semihost_sys_{read,write}
Fixes a minor bug in which a 64-bit guest on a 32-bit host could truncate the length. This would only ever cause a problem if there were no bits set in the low 32, so that it truncates to 0. Reviewed-by: Luc Michel <lmichel@kalray.eu> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'semihosting')
-rw-r--r--semihosting/syscalls.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/semihosting/syscalls.c b/semihosting/syscalls.c
index 5cb12d6adc..eefbae74f1 100644
--- a/semihosting/syscalls.c
+++ b/semihosting/syscalls.c
@@ -283,6 +283,14 @@ void semihost_sys_close(CPUState *cs, gdb_syscall_complete_cb complete, int fd)
void semihost_sys_read_gf(CPUState *cs, gdb_syscall_complete_cb complete,
GuestFD *gf, target_ulong buf, target_ulong len)
{
+ /*
+ * Bound length for 64-bit guests on 32-bit hosts, not overlowing ssize_t.
+ * Note the Linux kernel does this with MAX_RW_COUNT, so it's not a bad
+ * idea to do this unconditionally.
+ */
+ if (len > INT32_MAX) {
+ len = INT32_MAX;
+ }
switch (gf->type) {
case GuestFDGDB:
gdb_read(cs, complete, gf, buf, len);
@@ -313,6 +321,14 @@ void semihost_sys_read(CPUState *cs, gdb_syscall_complete_cb complete,
void semihost_sys_write_gf(CPUState *cs, gdb_syscall_complete_cb complete,
GuestFD *gf, target_ulong buf, target_ulong len)
{
+ /*
+ * Bound length for 64-bit guests on 32-bit hosts, not overlowing ssize_t.
+ * Note the Linux kernel does this with MAX_RW_COUNT, so it's not a bad
+ * idea to do this unconditionally.
+ */
+ if (len > INT32_MAX) {
+ len = INT32_MAX;
+ }
switch (gf->type) {
case GuestFDGDB:
gdb_write(cs, complete, gf, buf, len);