On 9/3/2026 2:55 PM, Peter Maydell wrote:
On Wed, 2 Sept 2026 at 05:43, Brian Cain <[email protected]> wrote:
From: Matheus Tavares Bernardino <[email protected]>

The Hexagon semihosting ABI extends the arm-compatible set with
operations like OPEN, WRITECREG, WRITE0, ISTTY, STAT, FSTAT, FTELL,
SEEK, FTRUNC, ACCESS, and GETCWD. Implement these trap0 handlers so
that baremetal programs using the standard Hexagon simulator ABI can
perform file I/O when running on qemu-system-hexagon.
Hi; Coverity points out an issue in the filename buffer handling
in this code.

-    /* TODO: implement other hexagon-specific semihosting calls */
+    case HEX_SYS_OPEN:
+    {
+        char filename[BUFSIZ];
+        target_ulong physical_filename_addr;
+        unsigned int filemode;
+        int length;
+        int real_openmode;
+        int ret, err = 0;
+        int i = 0;
+
+        hexagon_read_memory(env, swi_info, 4, &physical_filename_addr, 
retaddr);
+        hexagon_read_memory(env, swi_info + 4, 4, &filemode, retaddr);
+        hexagon_read_memory(env, swi_info + 8, 4, &length, retaddr);
+
+        if (length >= BUFSIZ) {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "%s: filename too large (%d)\n",
+                          __func__, length);
+            common_semi_cb(cs, -1, ENAMETOOLONG);
+            break;
+        }
+
+        do {
+            hexagon_read_memory(env, physical_filename_addr + i, 1,
+                                &filename[i], retaddr);
+            i++;
+        } while (filename[i - 1]);
Coverity didn't notice this one, but I did. We read into a local
buffer from guest memory, so we can't trust that the guest actually
put a NUL byte terminator in. If it doesn't, then we'll happily
keep loading from guest memory and overflow the filename[] array.
This needs a termination check involving sizeof(filename).

+    case HEX_SYS_STAT:
+    case HEX_SYS_FSTAT:
+    {
+        struct stat st_buf;
+        uint8_t *st_bufptr = (uint8_t *)&sys_stat;
+        int rc, err = 0;
+        char filename[BUFSIZ];
+        target_ulong physical_filename_addr;
+        target_ulong statBufferAddr;
+        hexagon_read_memory(env, swi_info, 4, &physical_filename_addr, 
retaddr);
+
+        if (what_swi == HEX_SYS_STAT) {
+            int i = 0;
+            do {
+                hexagon_read_memory(env, physical_filename_addr + i, 1,
+                                    &filename[i], retaddr);
+                i++;
+            } while ((i < BUFSIZ) && filename[i - 1]);
This one does have a check on BUFSIZ, but if we terminate the
loop because of that then filename[] won't be NUL terminated
and stat() might blow up when we pass it.

+            rc = stat(filename, &st_buf);
+            err = errno;
+    case HEX_SYS_ACCESS:
+    {
+        char filename[BUFSIZ];
+        uint32_t FileNameAddr;
+        uint32_t BufferMode;
+        int rc;
+
+        int i = 0;
+
+        hexagon_read_memory(env, swi_info, 4, &FileNameAddr, retaddr);
+        do {
+            hexagon_read_memory(env, FileNameAddr + i, 1, &filename[i],
+                                retaddr);
+            i++;
+        } while ((i < BUFSIZ) && (filename[i - 1]));
+        filename[i] = 0;
This one is wrong in yet a third way: we do check against
BUFSIZ, and we try to add in a possible missing NUL terminator,
but if we stopped the loop because i == BUFSIZ, then we will
write the NUL terminator off the end of the array.
(This is the one Coverity found: CID 1685942.)

Better still, can't we use the lock_user_string() handling that
the common-semihosting code does? That avoids all this need
for tedious manual byte-at-a-time looping and fixed sized buffers
and potential for bugs.


I'll investigate and fix the issues raised - thanks for pointing them out, Peter.



Reply via email to