镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Marshal Stacksize Integer Overflow leading to Frame Crash #158648

Description

@error-3317

Bug report

Description

In Python/marshal.c, The TYPE_CODE reader accepts stacksize from untrusted marshal data with zero validation: stacksize = (int)r_long(p);

Objects/codeobject.c:550, When the code object is created, co_framesize is computed: co->co_framesize = nlocalsplus + con->stacksize + FRAME_SPECIALS_SIZE;

With stacksize = INT_MAX (2147483647) and nlocalsplus = 3, this overflows the signed 32-bit int and becomes -2147483642.

Objects/frameobject.c:2118, Frame allocation does the same overflow:

int slots = code->co_nlocalsplus + code->co_stacksize;
PyFrameObject *f = PyObject_GC_NewVar(PyFrameObject, &PyFrame_Type, slots);

Python/pystate.c:3136, The interpreter's frame push has a bug:

_PyInterpreterFrame *_PyThreadState_PushFrame(PyThreadState *tstate, size_t size) {
    assert(size < INT_MAX/sizeof(PyObject *));  // Compiled out with -DNDEBUG
    if (_PyThreadState_HasStackSpace(tstate, (int)size)) { 
        _PyInterpreterFrame *res = (_PyInterpreterFrame *)tstate->datastack_top;
        tstate->datastack_top += size;
        return res;
    }
  • This bug only occurs when using tracing, causing discrepancy in behavior.

PoC

# main.py
import marshal, struct, types

code = compile("def f(a, b, c): return a + b + c", "<t>", "exec")
ns = {}; 
exec(code, ns)
func_code = ns['f'].__code__

# Patch stacksize to INT_MAX in the marshal stream
data = bytearray(marshal.dumps(func_code))
data[13:17] = struct.pack('<i', 0x7fffffff)  # stacksize field

# Load it: no error, valid code object
evil = marshal.loads(bytes(data))
func = types.FunctionType(evil, globals())

print("Running func without tracing...")
print(func(1, 2, 3))

import sys
sys.settrace(lambda f, e, a: None)
print("Running func with tracing...")
func(1, 2, 3)

Output

Running func without tracing...
6
Running func with tracing...
Traceback (most recent call last):
  File "main.py", line 22, in <module>
    func(1, 2, 3)
    ~~~~^^^^^^^^^
SystemError: Missing frame when calling trace function.

CPython versions tested on:

3.15

Operating systems tested on:

Linux

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

    pendingThe issue will be closed if no feedback is providedtype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions