[PATCH] util/cutils: Fix heap corruption under Windows

Bernhard Beschow posted 1 patch 2 weeks, 1 day ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20260414114033.2360-1-shentey@gmail.com
util/cutils.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
[PATCH] util/cutils: Fix heap corruption under Windows
Posted by Bernhard Beschow 2 weeks, 1 day ago
Under Windows, QEMU would only sporadically start successfully. In the
G_OS_WIN32 case, get_relocated_path() first determines a cursor
to the end of the "result" string and then increases its size with
g_string_set_size(). Since g_string_set_size() may reallocate, the
cursor may become dangling. Windows may detect this and crash the QEMU
process with the following message:

  HEAP: Free Heap block 000000000499B640 modified at 000000000499B684 after it was freed

Furthermore, QEMU crashes spontaneously, even long after the guest has
booted. For example, it presumably chrashes due to the guest setting a
new cursor icon which may be a result of the heap corruption.

Fix this by determining the cursor on the resized string.

Fixes: cf60ccc3306c ("cutils: Introduce bundle mechanism")
Cc: qemu-stable@nongnu.org
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
---
 util/cutils.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/util/cutils.c b/util/cutils.c
index 9803f11a59..76a9442085 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -1165,9 +1165,10 @@ char *get_relocated_path(const char *dir)
 
         PCWSTR wdir_skipped_root;
         if (PathCchSkipRoot(wdir, &wdir_skipped_root) == S_OK) {
+            char *cursor;
             size = wcsrtombs(NULL, &wdir_skipped_root, 0, &(mbstate_t){0});
-            char *cursor = result->str + result->len;
             g_string_set_size(result, result->len + size);
+            cursor = result->str + result->len - size;
             wcsrtombs(cursor, &wdir_skipped_root, size + 1, &(mbstate_t){0});
         } else {
             g_string_append(result, dir);
-- 
2.53.0
Re: [PATCH] util/cutils: Fix heap corruption under Windows
Posted by Peter Maydell 2 weeks, 1 day ago
On Tue, 14 Apr 2026 at 12:40, Bernhard Beschow <shentey@gmail.com> wrote:
>
> Under Windows, QEMU would only sporadically start successfully. In the
> G_OS_WIN32 case, get_relocated_path() first determines a cursor
> to the end of the "result" string and then increases its size with
> g_string_set_size(). Since g_string_set_size() may reallocate, the
> cursor may become dangling. Windows may detect this and crash the QEMU
> process with the following message:
>
>   HEAP: Free Heap block 000000000499B640 modified at 000000000499B684 after it was freed
>
> Furthermore, QEMU crashes spontaneously, even long after the guest has
> booted. For example, it presumably chrashes due to the guest setting a
> new cursor icon which may be a result of the heap corruption.
>
> Fix this by determining the cursor on the resized string.
>
> Fixes: cf60ccc3306c ("cutils: Introduce bundle mechanism")
> Cc: qemu-stable@nongnu.org
> Signed-off-by: Bernhard Beschow <shentey@gmail.com>

Thanks -- this isn't strictly a regression from 10.2 but it seems
worth getting into rc4, and the fix is clear and small, so I'm
going to apply it to git.

-- PMM
Re: [PATCH] util/cutils: Fix heap corruption under Windows
Posted by Akihiko Odaki 2 weeks, 1 day ago
On 2026/04/14 20:40, Bernhard Beschow wrote:
> Under Windows, QEMU would only sporadically start successfully. In the
> G_OS_WIN32 case, get_relocated_path() first determines a cursor
> to the end of the "result" string and then increases its size with
> g_string_set_size(). Since g_string_set_size() may reallocate, the
> cursor may become dangling. Windows may detect this and crash the QEMU
> process with the following message:
> 
>    HEAP: Free Heap block 000000000499B640 modified at 000000000499B684 after it was freed
> 
> Furthermore, QEMU crashes spontaneously, even long after the guest has
> booted. For example, it presumably chrashes due to the guest setting a
> new cursor icon which may be a result of the heap corruption.
> 
> Fix this by determining the cursor on the resized string.
> 
> Fixes: cf60ccc3306c ("cutils: Introduce bundle mechanism")
> Cc: qemu-stable@nongnu.org
> Signed-off-by: Bernhard Beschow <shentey@gmail.com>

Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>

Regards,
Akihiko Odaki
Re: [PATCH-for-11.0?] util/cutils: Fix heap corruption under Windows
Posted by Philippe Mathieu-Daudé 2 weeks, 1 day ago
On 14/4/26 13:40, Bernhard Beschow wrote:
> Under Windows, QEMU would only sporadically start successfully. In the
> G_OS_WIN32 case, get_relocated_path() first determines a cursor
> to the end of the "result" string and then increases its size with
> g_string_set_size(). Since g_string_set_size() may reallocate, the
> cursor may become dangling. Windows may detect this and crash the QEMU
> process with the following message:
> 
>    HEAP: Free Heap block 000000000499B640 modified at 000000000499B684 after it was freed
> 
> Furthermore, QEMU crashes spontaneously, even long after the guest has
> booted. For example, it presumably chrashes due to the guest setting a

(Typo "crashes")

> new cursor icon which may be a result of the heap corruption.
> 
> Fix this by determining the cursor on the resized string.
> 
> Fixes: cf60ccc3306c ("cutils: Introduce bundle mechanism")
> Cc: qemu-stable@nongnu.org
> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
> ---
>   util/cutils.c | 3 ++-
>   1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/util/cutils.c b/util/cutils.c
> index 9803f11a59..76a9442085 100644
> --- a/util/cutils.c
> +++ b/util/cutils.c
> @@ -1165,9 +1165,10 @@ char *get_relocated_path(const char *dir)
>   
>           PCWSTR wdir_skipped_root;
>           if (PathCchSkipRoot(wdir, &wdir_skipped_root) == S_OK) {
> +            char *cursor;
>               size = wcsrtombs(NULL, &wdir_skipped_root, 0, &(mbstate_t){0});
> -            char *cursor = result->str + result->len;
>               g_string_set_size(result, result->len + size);
> +            cursor = result->str + result->len - size;
>               wcsrtombs(cursor, &wdir_skipped_root, size + 1, &(mbstate_t){0});
>           } else {
>               g_string_append(result, dir);

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>