Skip to content

C extension should reject ext_hook=None consistently with the Python fallback #762

Closed

Description

@methane

Description

The C extension accepts ext_hook=None in both unpackb() and Unpacker.__init__(), while the pure-Python fallback raises TypeError.

In msgpack/_unpacker.pyx, init_ctx() only assigns ctx.user.ext_hook when ext_hook is not None:

if ext_hook is not None:
    if not PyCallable_Check(ext_hook):
        raise TypeError("ext_hook must be a callable.")
    ctx.user.ext_hook = <PyObject*>ext_hook

Unlike object_hook and list_hook, ctx.user.ext_hook is not initialized to NULL. This can leave an uninitialized pointer or retain a stale pointer when Unpacker.__init__() is called again.

Consequently, decoding extension types may invoke a stale callback or crash the process.

Expected behavior

Since ext_hook must be callable, the C extension should reject None and other non-callable values with TypeError, matching the pure-Python implementation.

Suggested fix

  • Initialize ctx.user.ext_hook to NULL along with object_hook and list_hook.
  • Remove the if ext_hook is not None condition and always validate that ext_hook is callable.
  • Add regression tests for both unpackb() and Unpacker, including reinitialization.

Credit

Thanks to @FanzyBear for reporting this issue and providing a detailed analysis and reproducer through a private security report.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions