Title: heap-buffer-overflow in functools.partial.__repr__() · Issue #144475 · python/cpython · GitHub
Open Graph Title: heap-buffer-overflow in functools.partial.__repr__() · Issue #144475 · python/cpython
X Title: heap-buffer-overflow in functools.partial.__repr__() · Issue #144475 · python/cpython
Description: Bug report Bug description: A heap-buffer-overflow vulnerability exists in CPython's functools.partial.__repr__() method due to improper handling of borrowed references during iteration over pto->args. Running with a Python interpreter c...
Open Graph Description: Bug report Bug description: A heap-buffer-overflow vulnerability exists in CPython's functools.partial.__repr__() method due to improper handling of borrowed references during iteration over pto->a...
X Description: Bug report Bug description: A heap-buffer-overflow vulnerability exists in CPython's functools.partial.__repr__() method due to improper handling of borrowed references during iteration over pt...
Opengraph URL: https://github.com/python/cpython/issues/144475
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"heap-buffer-overflow in functools.partial.__repr__()","articleBody":"# Bug report\n\n### Bug description:\n\nA heap-buffer-overflow vulnerability exists in CPython's `functools.partial.__repr__()` method due to improper handling of borrowed references during iteration over `pto-\u003eargs`.\n\nRunning with a Python interpreter compiled with ASAN (`./configure --with-address-sanitizer`):\n\u003cdetails\u003e \n\n```python\nimport gc \nfrom functools import partial \n\ng_partial = None \n\nclass EvilObject: \n def __init__(self, name, is_trigger=False): \n self.name = name \n self.is_trigger = is_trigger \n self.triggered = False \n \n def __repr__(self): \n global g_partial \n if self.is_trigger and not self.triggered and g_partial is not None: \n self.triggered = True \n # Replace args via __setstate__, this frees the old tuple \n new_state = (lambda x: x, (\"replaced\",), {}, None) \n g_partial.__setstate__(new_state) \n gc.collect() \n return f\"EvilObject({self.name})\" \n \nevil1 = EvilObject(\"trigger\", is_trigger=True) \nevil2 = EvilObject(\"victim1\") \nevil3 = EvilObject(\"victim2\") \nevil4 = EvilObject(\"victim3\") \nevil5 = EvilObject(\"victim4\") \n\np = partial(lambda: None, evil1, evil2, evil3, evil4, evil5) \ng_partial = p \n\ndel evil1, evil2, evil3, evil4, evil5 \n\nrepr(p) \n```\n\u003c/details\u003e\n\nAsan output:\n\u003cdetails\u003e\n\n```\n=================================================================\n==430879==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x5060000d4878 at pc 0x5c4743c6d881 bp 0x7ffc1076d330 sp 0x7ffc1076d320\nREAD of size 8 at 0x5060000d4878 thread T0\n #0 0x5c4743c6d880 in partial_repr Modules/_functoolsmodule.c:712\n #1 0x5c47436f8158 in PyObject_Repr Objects/object.c:779\n #2 0x5c47436f8158 in PyObject_Repr Objects/object.c:754\n #3 0x5c47435da5ef in _PyObject_VectorcallTstate Include/internal/pycore_call.h:136\n #4 0x5c47435da5ef in PyObject_Vectorcall Objects/call.c:327\n #5 0x5c474394258e in _Py_VectorCallInstrumentation_StackRefSteal Python/ceval.c:762\n #6 0x5c4743498fc3 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1809\n #7 0x5c474394f069 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:118\n #8 0x5c474394f069 in _PyEval_Vector Python/ceval.c:2097\n #9 0x5c474394f069 in PyEval_EvalCode Python/ceval.c:673\n #10 0x5c4743a8f6ed in run_eval_code_obj Python/pythonrun.c:1366\n #11 0x5c4743a8f6ed in run_mod Python/pythonrun.c:1469\n #12 0x5c4743a9456e in pyrun_file Python/pythonrun.c:1294\n #13 0x5c4743a9456e in _PyRun_SimpleFileObject Python/pythonrun.c:518\n #14 0x5c4743a94fbb in _PyRun_AnyFileObject Python/pythonrun.c:81\n #15 0x5c4743b0a0e9 in pymain_run_file_obj Modules/main.c:410\n #16 0x5c4743b0a0e9 in pymain_run_file Modules/main.c:429\n #17 0x5c4743b0a0e9 in pymain_run_python Modules/main.c:691\n #18 0x5c4743b0b7de in Py_RunMain Modules/main.c:772\n #19 0x5c4743b0b7de in pymain_main Modules/main.c:802\n #20 0x5c4743b0b7de in Py_BytesMain Modules/main.c:826\n #21 0x7005d3e29d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58\n #22 0x7005d3e29e3f in __libc_start_main_impl ../csu/libc-start.c:392\n #23 0x5c47434b8d34 in _start (/home/or4nge/cpython/python+0x20cd34)\n\n0x5060000d4878 is located 0 bytes to the right of 56-byte region [0x5060000d4840,0x5060000d4878)\nallocated by thread T0 here:\n #0 0x7005d42b4887 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145\n #1 0x5c47439e5079 in _PyObject_MallocWithType Include/internal/pycore_object_alloc.h:46\n #2 0x5c47439e5079 in gc_alloc Python/gc.c:2352\n #3 0x5c47439e5079 in _PyObject_GC_NewVar Python/gc.c:2394\n #4 0x5c4743762d6a in tuple_alloc Objects/tupleobject.c:57\n #5 0x5c47437657b7 in PyTuple_New Objects/tupleobject.c:81\n #6 0x5c47437657b7 in PyTuple_New Objects/tupleobject.c:75\n #7 0x5c47439cad7f in fold_tuple_of_constants Python/flowgraph.c:1470\n #8 0x5c47439cad7f in optimize_basic_block Python/flowgraph.c:2337\n #9 0x5c47439cf342 in optimize_cfg Python/flowgraph.c:2546\n #10 0x5c47439cf342 in _PyCfg_OptimizeCodeUnit Python/flowgraph.c:3658\n #11 0x5c4743992c7a in optimize_and_assemble_code_unit Python/compile.c:1439\n #12 0x5c4743992c7a in _PyCompile_OptimizeAndAssemble Python/compile.c:1481\n #13 0x5c4743988122 in codegen_function_body Python/codegen.c:1411\n #14 0x5c4743988122 in codegen_function Python/codegen.c:1503\n #15 0x5c4743979224 in codegen_visit_stmt Python/codegen.c:3029\n #16 0x5c474397fa1a in codegen_body Python/codegen.c:929\n #17 0x5c474398142f in codegen_class_body Python/codegen.c:1592\n #18 0x5c474398142f in codegen_class Python/codegen.c:1685\n #19 0x5c474397b86a in codegen_visit_stmt Python/codegen.c:3031\n #20 0x5c474397fa1a in codegen_body Python/codegen.c:929\n #21 0x5c474398ade2 in _PyCodegen_Module Python/codegen.c:892\n #22 0x5c474398d148 in compiler_codegen Python/compile.c:841\n #23 0x5c47439930f6 in compiler_mod Python/compile.c:862\n #24 0x5c47439930f6 in _PyAST_Compile Python/compile.c:1494\n #25 0x5c4743a8f4d0 in run_mod Python/pythonrun.c:1419\n #26 0x5c4743a9456e in pyrun_file Python/pythonrun.c:1294\n #27 0x5c4743a9456e in _PyRun_SimpleFileObject Python/pythonrun.c:518\n #28 0x5c4743a94fbb in _PyRun_AnyFileObject Python/pythonrun.c:81\n #29 0x5c4743b0a0e9 in pymain_run_file_obj Modules/main.c:410\n #30 0x5c4743b0a0e9 in pymain_run_file Modules/main.c:429\n #31 0x5c4743b0a0e9 in pymain_run_python Modules/main.c:691\n #32 0x5c4743b0b7de in Py_RunMain Modules/main.c:772\n #33 0x5c4743b0b7de in pymain_main Modules/main.c:802\n #34 0x5c4743b0b7de in Py_BytesMain Modules/main.c:826\n #35 0x7005d3e29d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58\n\nSUMMARY: AddressSanitizer: heap-buffer-overflow Modules/_functoolsmodule.c:712 in partial_repr\nShadow bytes around the buggy address:\n 0x0a0c800128b0: fa fa fa fa fd fd fd fd fd fd fd fa fa fa fa fa\n 0x0a0c800128c0: 00 00 00 00 00 00 00 00 fa fa fa fa fd fd fd fd\n 0x0a0c800128d0: fd fd fd fd fa fa fa fa 00 00 00 00 00 00 00 00\n 0x0a0c800128e0: fa fa fa fa 00 00 00 00 00 00 00 00 fa fa fa fa\n 0x0a0c800128f0: 00 00 00 00 00 00 00 fa fa fa fa fa 00 00 00 00\n=\u003e0x0a0c80012900: 00 00 00 00 fa fa fa fa 00 00 00 00 00 00 00[fa]\n 0x0a0c80012910: fa fa fa fa 00 00 00 00 00 00 00 fa fa fa fa fa\n 0x0a0c80012920: 00 00 00 00 00 00 00 00 fa fa fa fa fd fd fd fd\n 0x0a0c80012930: fd fd fd fa fa fa fa fa fd fd fd fd fd fd fd fa\n 0x0a0c80012940: fa fa fa fa fd fd fd fd fd fd fd fa fa fa fa fa\n 0x0a0c80012950: 00 00 00 00 00 00 00 00 fa fa fa fa 00 00 00 00\nShadow byte legend (one shadow byte represents 8 application bytes):\n Addressable: 00\n Partially addressable: 01 02 03 04 05 06 07\n Heap left redzone: fa\n Freed heap region: fd\n Stack left redzone: f1\n Stack mid redzone: f2\n Stack right redzone: f3\n Stack after return: f5\n Stack use after scope: f8\n Global redzone: f9\n Global init order: f6\n Poisoned by user: f7\n Container overflow: fc\n Array cookie: ac\n Intra object redzone: bb\n ASan internal: fe\n Left alloca redzone: ca\n Right alloca redzone: cb\n Shadow gap: cc\n==430879==ABORTING\n```\n\n\u003c/details\u003e\n\n### CPython versions tested on:\n\nCPython main branch\n\n### Operating systems tested on:\n\nLinux\n\n\u003c!-- gh-linked-prs --\u003e\n### Linked PRs\n* gh-144571\n* gh-145362\n* gh-145395\n* gh-145470\n* gh-145882\n\u003c!-- /gh-linked-prs --\u003e","author":{"url":"https://github.com/Qanux","@type":"Person","name":"Qanux"},"datePublished":"2026-02-04T15:27:02.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":2},"url":"https://github.com/144475/cpython/issues/144475"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:e49ae33e-0a4f-320a-8d35-f0f46541285f |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | 9630:36E597:589295B:7CC023F:6A4FFA8F |
| html-safe-nonce | d531203eebc0855b742f5c2bb70c9d2f65fd479262b9a3c22ffc668497121ea8 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI5NjMwOjM2RTU5Nzo1ODkyOTVCOjdDQzAyM0Y6NkE0RkZBOEYiLCJ2aXNpdG9yX2lkIjoiMjI0ODUyNDYwMjI1Nzk2MzY2MyIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | 749369a77bd52b5a3eb791cc9a9a038ce8d92d9b1c70a158e6ad802ffab3f923 |
| hovercard-subject-tag | issue:3897097620 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/python/cpython/144475/issue_layout |
| twitter:image | https://opengraph.githubassets.com/9dff4c9e9023e0ab09a9b5511a5a5786c0129cda6f9838cfe66ad7544a6503a2/python/cpython/issues/144475 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/9dff4c9e9023e0ab09a9b5511a5a5786c0129cda6f9838cfe66ad7544a6503a2/python/cpython/issues/144475 |
| og:image:alt | Bug report Bug description: A heap-buffer-overflow vulnerability exists in CPython's functools.partial.__repr__() method due to improper handling of borrowed references during iteration over pto->a... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | Qanux |
| hostname | github.com |
| expected-hostname | github.com |
| None | 3bd0ff5d28a87b4801a63fb38c2a21a91b0a700dca159dc9416aeae05771b899 |
| turbo-cache-control | no-preview |
| go-import | github.com/python/cpython git https://github.com/python/cpython.git |
| octolytics-dimension-user_id | 1525981 |
| octolytics-dimension-user_login | python |
| octolytics-dimension-repository_id | 81598961 |
| octolytics-dimension-repository_nwo | python/cpython |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 81598961 |
| octolytics-dimension-repository_network_root_nwo | python/cpython |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 67a336083e4dcb40224dc2c01cd4c7ed413bdb09 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width