Skip to content

Pass a full-width size_t to the compat setparam/getparam - #371

Open
herniqeu wants to merge 2 commits into
ahupp:masterfrom
herniqeu:fix/compat-setparam-size-t
Open

herniqeu wants to merge 2 commits into
ahupp:masterfrom
herniqeu:fix/compat-setparam-size-t

Conversation

@herniqeu

@herniqeu herniqeu commented Nov 1, 2026

Copy link
Copy Markdown

Root cause

magic/compat.py builds a ctypes.c_int (4 bytes) buffer for magic_setparam/magic_getparam, but libmagic dereferences that pointer as a size_t (ms->bytes_max = *(const size_t *)value in file's func.c):

    def getparam(self, param):
        v = c_int()
        i = _getparam(self._magic_t, param, byref(v))
...
    def setparam(self, param, value):
        v = c_int(value)
        return _setparam(self._magic_t, param, byref(v))

On 64-bit this has three real effects: setparam silently truncates values above 32 bits and still reports success, getparam lets libmagic write 8 bytes into a 4-byte buffer, and the write path hands libmagic 4 uninitialized adjacent bytes. magic/__init__.py already uses c_size_t (it was fixed there before); only the compat layer, added later, was left with c_int.

Reproduction (Python 3.11, libmagic 5.44, Linux x64)

import magic.compat as c
m = c.open(c.MAGIC_NONE)
m.setparam(c.PARAM_BYTES_MAX, 2**33)   # returns 0 ("success")
m.getparam(c.PARAM_BYTES_MAX)          # master: 0  (bytes_max became 0, which
                                       #         zeroes libmagic's read limit)
                                       # expected: 8589934592

Setting bytes_max to 0 breaks identification for every later from_* call on that handle, so the truncation is not cosmetic.

Fix

Use c_size_t in the compat getparam/setparam, as magic/__init__.py already does.

Coverage

New test_compat_params_use_size_t in test/python_magic_test.py: sets PARAM_BYTES_MAX to 2**33 and reads it back. It fails on master (AssertionError: 8589934592 != 0) and passes with the patch. Full suites: python_magic_test 14 tests OK (2 skipped), libmagic_test 3 tests OK.

(The test file requires export LC_ALL=en_US.UTF-8, as the suite's own guard asks.)

libmagic reads and writes the value of magic_setparam/magic_getparam as a
size_t, but magic/compat.py built a c_int buffer instead. On 64-bit that
truncated values above 32 bits before they reached libmagic (and
getparam let libmagic write 8 bytes into a 4-byte buffer).
magic/__init__.py already uses c_size_t; only the compat layer was left
behind.
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.

1 participant