Skip to content

Claude Code Review Report #4214

Description

@qarmin

I ran Claude Code to look for potential issues, including logic bugs, copy-paste errors, architecture problems, panics, and similar issues.

I don't have much experience with low-level C and assembly, so I wasn't able to properly verify most of these findings myself. However, I reported a similar set of findings to the FEX project, and the author fixed most of the issues I reported(FEX-Emu/FEX#5678).

The full report - box64_20260807.html

Here are a few example findings that I'm almost certain are actual bugs:

CPY_4 CRITICAL

Description: my32_XFreeFontSet frees set->names[i] in both cleanup loops; the second loop iterates over
set->fonts_size but still frees from the set->names array. When a program called both
XFontsOfFontSet(..., fonts, names) variants, the same set->names[i] block is passed to
box32_free() twice (double free / heap corruption), the set->fonts[i] blocks are leaked, and if
fonts_size > names_size the loop reads past the end of set->names.

Locations:

EXPORT void my32_XFreeFontSet(x64emu_t* emu,void* dpy, my_XFontSet_32_t* set)
{
my->XFreeFontSet(dpy, set->fontset);
for(int i=0; i<set->names_size; ++i)
box32_free(set->names[i]);
box32_free(set->names);
for(int i=0; i<set->fonts_size; ++i)
box32_free(set->names[i]);
box32_free(set->fonts);
box32_free(set);
}

Fix:

    for(int i=0; i<set->fonts_size; ++i)
-        box32_free(set->names[i]);
+        box32_free(set->fonts[i]);
    box32_free(set->fonts);

CPY_49 HIGH

Description: my32_glBindBuffersRange converts both the offsets and the sizes arrays from 32-bit long_t to native
64-bit long, but then passes the unconverted guest array sizes to the native entry point instead of
sizes_l. The native driver therefore reads count 64-bit GLsizeiptr values out of a buffer that only holds
count 32-bit values: every size is wrong (two adjacent 32-bit sizes merged into one 64-bit value) and the read
runs 4 * count bytes past the end of the guest array. The very next functions in the same file
(my32_glBindVertexBuffers, my32_glVertexArrayVertexBuffers) pass their converted array correctly, which
makes this an obvious editing slip. The bug is duplicated verbatim in wrappedlibglxnvidia.c.

Locations:

EXPORT void my32_glBindBuffersRange(x64emu_t* emu, uint32_t target, uint32_t first, int count, void* buffers, ptr_t* offsets, ptr_t* sizes)
{
vFuuippp_t fnc = getBridgeFnc2((void*)R_RIP);
if(!fnc) fnc=my->glBindBuffersRange;
long offsets_l[count];
long sizes_l[count];
for(int i=0; i<count; ++i) {
offsets_l[i] = from_long(offsets[i]);
sizes_l[i] = from_long(sizes[i]);
}
fnc(target, first, count, buffers, offsets_l, sizes);
}

EXPORT void my32nv_glBindBuffersRange(x64emu_t* emu, uint32_t target, uint32_t first, int count, void* buffers, ptr_t* offsets, ptr_t* sizes)
{
vFuuippp_t fnc = getBridgeFnc2((void*)R_RIP);
if(!fnc) fnc=my->glBindBuffersRange;
long offsets_l[count];
long sizes_l[count];
for(int i=0; i<count; ++i) {
offsets_l[i] = from_long(offsets[i]);
sizes_l[i] = from_long(sizes[i]);
}
fnc(target, first, count, buffers, offsets_l, sizes);
}

Fix: Before: fnc(target, first, count, buffers, offsets_l, sizes);

After: fnc(target, first, count, buffers, offsets_l, sizes_l);

Apply the same one-word change in my32nv_glBindBuffersRange.

CPY_75 MEDIUM

Description: In all four xcb connection converters the xid.max field is filled from source->xid.last instead of
source->xid.max. last and max are different members of my_xcb_xid_t / x64_xcb_xid_t
(last is the last handed-out XID, max is the end of the currently reserved range), so after any conversion the
guest/host sees max == last, which makes libxcb believe the XID range is exhausted on every allocation.
The bug is duplicated in align_xcb_connection, unalign_xcb_connection, align_xcb_connection32 and
unalign_xcb_connection32.

Locations:

box64/src/libtools/myalign.c

Lines 1660 to 1663 in 2f130fa

dest->xid.base = source->xid.base;
dest->xid.inc = source->xid.inc;
dest->xid.last = source->xid.last;
dest->xid.max = source->xid.last;

box64/src/libtools/myalign.c

Lines 1698 to 1701 in 2f130fa

dest->xid.base = source->xid.base;
dest->xid.inc = source->xid.inc;
dest->xid.last = source->xid.last;
dest->xid.max = source->xid.last;

dest->xid.base = source->xid.base;
dest->xid.inc = source->xid.inc;
dest->xid.last = source->xid.last;
dest->xid.max = source->xid.last;

dest->xid.base = source->xid.base;
dest->xid.inc = source->xid.inc;
dest->xid.last = source->xid.last;
dest->xid.max = source->xid.last;

Fix:

// before
    dest->xid.max = source->xid.last;
// after
    dest->xid.max = source->xid.max;

Apply in all four places.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions