Skip to content

Fix Windows crashes and data corruption when flashing large ROMs - #10

Open
MaChInEgUn3 wants to merge 1 commit into
MiForge:mainfrom
MaChInEgUn3:fix/windows-large-rom-flashing
Open

Fix Windows crashes and data corruption when flashing large ROMs#10
MaChInEgUn3 wants to merge 1 commit into
MiForge:mainfrom
MaChInEgUn3:fix/windows-large-rom-flashing

Conversation

@MaChInEgUn3

@MaChInEgUn3 MaChInEgUn3 commented Aug 20, 2026

Copy link
Copy Markdown

Fixes #7

Summary

While flashing a 6.8GB official recovery ROM (POCO X7 Pro, rodin_global) on Windows, the tool consistently either crashed with STATUS_HEAP_CORRUPTION (choice 2/3) or silently corrupted/aborted the sideload transfer partway through (device rebooting mid-flash). Bisected this down to four separate bugs in miasst.c, all confirmed with a debug build against real hardware.

Bugs fixed

  1. Heap buffer overflow in validate_check()post_buf is allocated only large enough for the outgoing request, but is reused to hold the server's decoded/decrypted response, which is usually larger. Overflows the heap buffer as soon as a response doesn't fit.
  2. Use-after-free in validate_check()post_buf was free()'d immediately after the curl request succeeded, but is still read (via json_create()'s in-place parsing) for the rest of the function. This is probably the real root cause of the heap corruption above — the undersized buffer just changed how visibly it crashed.
  3. NULL pointer dereference in validate_check() (choice 2, "ROMs that can be flashed")tiny-json's json_getSibling()/json_getName() dereference their argument with no NULL check. A response object with 0 or 1 top-level property crashes.
  4. Binary data corruption + 32-bit overflow in start_sideload() — the ROM file was opened in text mode ("r") instead of binary ("rb"), which on Windows makes the CRT treat byte 0x1A as EOF and rewrite CRLF sequences mid-transfer. Separately, file_size/block/offset/total_sent were long, which is 32-bit on Windows (LLP64) even in a 64-bit build — any ROM over ~2GB (i.e. basically every recovery ROM this tool flashes) overflows these, corrupting the announced file size and per-chunk offsets and aborting the transfer partway through.

Testing

Flashed a 6.3GB rodin_global recovery ROM end-to-end on Windows 11 after these fixes; completed successfully (Installation_complete.) where the unmodified build crashed or hung on every attempt.

_fseeki64/_ftelli64 are used on Windows; fseeko/ftello are used elsewhere (Linux/macOS/Termux) to keep the fix portable across the platforms this project builds for.

Found while debugging why flashing a 6.8GB recovery ROM on Windows
reliably crashed or corrupted the transfer. All four issues below were
confirmed with a debug build against real hardware (POCO X7 Pro).

- validate_check(): post_buf is allocated just large enough for the
  outgoing request, but is reused to hold the server's decoded/decrypted
  response, which is usually bigger. Overflowed the heap buffer
  (STATUS_HEAP_CORRUPTION on Windows) as soon as a response didn't fit.

- validate_check(): post_buf was free()'d right after the curl request
  succeeded, but is read through json_create()'s in-place parsing for
  the rest of the function - a use-after-free on every successful
  request. This is likely the real root cause behind the heap
  corruption above; the oversized buffer just changed how visibly it
  crashed.

- validate_check() (choice 2, "ROMs that can be flashed"): tiny-json's
  json_getSibling()/json_getName() dereference their argument without a
  NULL check. A response object with 0 or 1 top-level property crashed
  with a NULL pointer dereference.

- start_sideload(): the ROM file was opened in text mode ("r") instead
  of binary ("rb"). On Windows this makes the CRT treat byte 0x1A as
  EOF and rewrite CRLF sequences, corrupting whatever binary ROM data
  follows the first occurrence.

- start_sideload(): file_size/block/offset/total_sent were `long`,
  which is 32-bit on Windows (LLP64) even in a 64-bit build. Any ROM
  over ~2GB - i.e. basically every recovery ROM this tool flashes -
  overflows these, corrupting the sideload-host size announced to the
  device and the per-chunk file offsets, aborting the transfer partway
  through (observed as the device silently rebooting mid-flash).
  Widened to 64-bit and switched to _fseeki64/_ftelli64 on Windows
  (fseeko/ftello elsewhere) to seek past the 2GB mark correctly.

Tested end-to-end flashing a 6.3GB rodin_global recovery ROM on
Windows 11 after these fixes; completed successfully where the
unmodified build crashed or hung every time.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

miasst_windows64.exe has stopped responding

1 participant