Skip to content

Instantly share code, notes, and snippets.

@vassvik
Created April 2, 2026 08:15
Show Gist options
  • Select an option

  • Save vassvik/f73ffdea431407fcd65b60ff6c183ef6 to your computer and use it in GitHub Desktop.

Select an option

Save vassvik/f73ffdea431407fcd65b60ff6c183ef6 to your computer and use it in GitHub Desktop.
Bug: read_reg_string uses UTF-16 byte count to slice UTF-8 output buffer (core/sys/info/platform_windows.odin)

Bug: read_reg_string uses UTF-16 byte count to slice UTF-8 output buffer

File: core/sys/info/platform_windows.odin, line 385

Introduced in: the update-odin-2026-02 merge that removed context/temp allocator usage from init_gpu_info and read_reg_string.

The bug

utf16.decode_to_utf8(res_buf[:result_size], buf_utf16[:])

RegGetValueW writes the number of bytes consumed in the UTF-16 output buffer back into result_size. For the string "NVIDIA RTX PRO 5000 Blackwell Generation Laptop GPU" (51 chars + null terminator = 52 UTF-16 code units = 104 bytes), result_size comes back as 104.

This value is then used to slice res_buf, the UTF-8 destination buffer, as res_buf[:104]. But res_buf is backed by buf_scratch: [100]u8 at the call site (line 302), so the slice 0:104 is out of range for a 100-element buffer.

Runtime error:

platform_windows.odin(385:30) Invalid slice indices 0:104 is out of range 0..<100

Why it only hits certain machines

The crash triggers when DriverDesc (or ProviderName) exceeds 50 characters, making the UTF-16 byte count exceed 100. Example from an affected machine:

Entry Value UTF-8 len UTF-16 bytes (incl null)
0000 ProviderName NVIDIA 6 14
0000 DriverDesc NVIDIA RTX PRO 5000 Blackwell Generation Laptop GPU 51 104
0001 ProviderName Intel Corporation 17 36
0001 DriverDesc Intel(R) Graphics 17 36

The "Blackwell Generation Laptop GPU" branding pushes it over. Shorter GPU names like NVIDIA GeForce RTX 4090 (23 chars, 48 UTF-16 bytes) would never trigger this.

Two issues

  1. Wrong size domain: result_size is in UTF-16 bytes, but it's indexing the UTF-8 destination. The destination should be the full res_buf, and the source should be buf_utf16[:result_size / size_of(u16)].
  2. buf_scratch is too small: even with correct slicing, a [100]u8 buffer can't hold strings approaching 100 characters. The old code used a 4096-byte temp-allocated buffer. The scratch buffer used in format_display_version a few lines above is [512]u8.

Suggested fix

// line 385: use full res_buf as destination, convert byte count to u16 count for source
utf16.decode_to_utf8(res_buf, buf_utf16[:result_size / size_of(u16)])

And bump buf_scratch on line 302 from [100]u8 to [512]u8.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment