When semihosting 32-bit systems, the return value of FLEN will be stored
in a 32-bit integer. To prevent wraparound, return -1 and set EOVERFLOW.
This matches the behavior of stat(2). Static files don't need to be
checked, since are always small.

Signed-off-by: Sean Anderson <[email protected]>
---

 semihosting/arm-compat-semi.c | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/semihosting/arm-compat-semi.c b/semihosting/arm-compat-semi.c
index c5a07cb947..57453ca6be 100644
--- a/semihosting/arm-compat-semi.c
+++ b/semihosting/arm-compat-semi.c
@@ -305,8 +305,19 @@ static uint64_t common_semi_flen_buf(CPUState *cs)
     return sp - 64;
 }
 
+static void common_semi_flen_cb(CPUState *cs, uint64_t ret, int err)
+{
+    CPUArchState *env = cpu_env(cs);
+
+    if (!err && !is_64bit_semihosting(env) && ret > INT32_MAX) {
+            ret = -1, err = EOVERFLOW;
+    }
+    common_semi_cb(cs, ret, err);
+}
+
+
 static void
-common_semi_flen_fstat_cb(CPUState *cs, uint64_t ret, int err)
+common_semi_flen_gdb_cb(CPUState *cs, uint64_t ret, int err)
 {
     if (!err) {
         /* The size is always stored in big-endian order, extract the value. */
@@ -319,7 +330,7 @@ common_semi_flen_fstat_cb(CPUState *cs, uint64_t ret, int 
err)
             ret = be64_to_cpu(size);
         }
     }
-    common_semi_cb(cs, ret, err);
+    common_semi_flen_cb(cs, ret, err);
 }
 
 static void
@@ -517,7 +528,7 @@ void do_common_semihosting(CPUState *cs)
 
     case TARGET_SYS_FLEN:
         GET_ARG(0);
-        semihost_sys_flen(cs, common_semi_flen_fstat_cb, common_semi_cb,
+        semihost_sys_flen(cs, common_semi_flen_gdb_cb, common_semi_flen_cb,
                           arg0, common_semi_flen_buf(cs));
         break;
 
-- 
2.35.1.1320.gc452695387.dirty


Reply via email to