Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Null pointer dereference in array_repeat via re-entrant __index__ during array multiplication #142883

Open
Labels
extension-modulesC modules in the Modules dir type-crashA hard crash of the interpreter, possibly with a core dump
@jackfromeast

Description

Important

This issue is not for newcomers.

What happened?

A custom __index__ can swap the MRO of an array.array subclass mid multiplication, so array_repeat calls find_array_state_by_type on a type without the array module and receives a NULL module state. The subsequent dereference of state->ArrayType then hits freed memory and triggers a null pointer read.

Proof of Concept:

import array
class Good(array.array):
 pass
class Hide(type):
 def mro(cls):
 return (cls, object)
class Bad(Good, metaclass=Hide):
 pass
arr = Good('b', b'x')
class Count:
 def __index__(self):
 arr.__class__ = Bad # Drop array.array from the MRO mid-op
 return 2
arr * Count()

Affected Versions:

Details
Python Version Status Exit Code
Python 3.9.24+ (heads/3.9:111bbc15b26, Oct 27 2025, 21:34:13) OK 0
Python 3.10.19+ (heads/3.10:014261980b1, Oct 27 2025, 21:19:00) [Clang 18.1.3 (1ubuntu1)] ASAN 1
Python 3.11.14+ (heads/3.11:88f3f5b5f11, Oct 27 2025, 21:20:35) [Clang 18.1.3 (1ubuntu1)] ASAN 1
Python 3.12.12+ (heads/3.12:8cb2092bd8c, Oct 27 2025, 21:27:07) [Clang 18.1.3 (1ubuntu1)] ASAN 1
Python 3.13.9+ (heads/3.13:9c8eade20c6, Oct 27 2025, 21:28:49) [Clang 18.1.3 (1ubuntu1)] ASAN 1
Python 3.14.0+ (heads/3.14:2e216728038, Oct 27 2025, 21:30:55) [Clang 18.1.3 (1ubuntu1)] ASAN 1
Python 3.15.0a1+ (heads/main:f5394c257ce, Oct 27 2025, 21:32:37) [Clang 18.1.3 (1ubuntu1)] ASAN 1

Related Code Snippet

Details
#define find_array_state_by_type(tp) \
 (get_array_state(PyType_GetModuleByDef(tp, &arraymodule))) // requires array.array in the MRO
static array_state *
get_array_state(PyObject *module)
{
 return (array_state *)_PyModule_GetState(module); // assumes module is non-NULL
}
static PyObject *
array_repeat(PyObject *op, Py_ssize_t n)
{
 arrayobject *a = arrayobject_CAST(op);
 array_state *state = find_array_state_by_type(Py_TYPE(a));
 if (n < 0)
 n = 0;
 const Py_ssize_t array_length = Py_SIZE(a);
 if ((array_length != 0) && (n > PY_SSIZE_T_MAX / array_length)) {
 return PyErr_NoMemory();
 }
 Py_ssize_t size = array_length * n;
 arrayobject* np = (arrayobject *) newarrayobject(state->ArrayType, size, a->ob_descr);
 if (np == NULL)
 return NULL;
 if (size == 0)
 return (PyObject *)np;
 const Py_ssize_t oldbytes = array_length * a->ob_descr->itemsize;
 const Py_ssize_t newbytes = oldbytes * n;
 _PyBytes_Repeat(np->ob_item, newbytes, a->ob_item, oldbytes);
 return (PyObject *)np;
}

Sanitizer Report

Details
=================================================================
==105120==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000008 (pc 0x77b5659592d8 bp 0x7ffe28c17cf0 sp 0x7ffe28c17cf0 T0)
==105120==The signal is caused by a READ memory access.
==105120==Hint: address points to the zero page.
 #0 0x77b5659592d8 in _Py_TYPE Include/object.h:277
 #1 0x77b5659592d8 in Py_IS_TYPE Include/object.h:302
 #2 0x77b5659592d8 in PyObject_TypeCheck Include/object.h:432
 #3 0x77b565959317 in _PyModule_GetState Include/internal/pycore_moduleobject.h:38
 #4 0x77b56595936b in get_array_state Modules/arraymodule.c:75
 #5 0x77b56595f09d in array_repeat Modules/arraymodule.c:970
 #6 0x584ac280512b in wrap_indexargfunc Objects/typeobject.c:9651
 #7 0x584ac270d606 in wrapperdescr_raw_call Objects/descrobject.c:532
 #8 0x584ac270df48 in wrapperdescr_call Objects/descrobject.c:570
 #9 0x584ac26eec71 in _PyObject_MakeTpCall Objects/call.c:242
 #10 0x584ac2801605 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:167
 #11 0x584ac2801680 in vectorcall_unbound Objects/typeobject.c:3033
 #12 0x584ac281def4 in vectorcall_maybe Objects/typeobject.c:3130
 #13 0x584ac2821819 in slot_nb_multiply Objects/typeobject.c:10397
 #14 0x584ac26b8613 in binary_op1 Objects/abstract.c:966
 #15 0x584ac26bcc64 in PyNumber_Multiply Objects/abstract.c:1170
 #16 0x584ac29638f8 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:62
 #17 0x584ac29b0e54 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121
 #18 0x584ac29b1148 in _PyEval_Vector Python/ceval.c:2001
 #19 0x584ac29b13f8 in PyEval_EvalCode Python/ceval.c:884
 #20 0x584ac2aa8507 in run_eval_code_obj Python/pythonrun.c:1365
 #21 0x584ac2aa8723 in run_mod Python/pythonrun.c:1459
 #22 0x584ac2aa957a in pyrun_file Python/pythonrun.c:1293
 #23 0x584ac2aac220 in _PyRun_SimpleFileObject Python/pythonrun.c:521
 #24 0x584ac2aac4f6 in _PyRun_AnyFileObject Python/pythonrun.c:81
 #25 0x584ac2afd74d in pymain_run_file_obj Modules/main.c:410
 #26 0x584ac2afd9b4 in pymain_run_file Modules/main.c:429
 #27 0x584ac2aff1b2 in pymain_run_python Modules/main.c:691
 #28 0x584ac2aff842 in Py_RunMain Modules/main.c:772
 #29 0x584ac2affa2e in pymain_main Modules/main.c:802
 #30 0x584ac2affdb3 in Py_BytesMain Modules/main.c:826
 #31 0x584ac2583645 in main Programs/python.c:15
 #32 0x77b56622a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
 #33 0x77b56622a28a in __libc_start_main_impl ../csu/libc-start.c:360
 #34 0x584ac2583574 in _start (/home/jackfromeast/Desktop/entropy/targets/grammar-afl++-latest/targets/cpython/python+0x2dd574) (BuildId: 202d5dbb945f6d5f5a66ad50e2688d56affd6ecb)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV Include/object.h:277 in _Py_TYPE
==105120==ABORTING

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    extension-modulesC modules in the Modules dir type-crashA hard crash of the interpreter, possibly with a core dump

    Projects

    No projects

    Milestone

    No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

        AltStyle によって変換されたページ (->オリジナル) /