Repository navigation
Use-after-free in dict/list #82769
Copy link
Copy link
Closed
Labels
3.7 (EOL)end of lifeend of life3.8 (EOL)end of lifeend of life3.9 (EOL)end of lifeend of lifeinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)type-crashA hard crash of the interpreter, possibly with a core dumpA hard crash of the interpreter, possibly with a core dump
Description
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee = None
closed_at = <Date 2019-12-31.04:16:45.105>
created_at = <Date 2019-10-25.13:25:50.889>
labels = ['interpreter-core', '3.7', '3.8', '3.9', 'type-crash']
title = 'Use-after-free in dict/list'
updated_at = <Date 2019-12-31.04:16:45.104>
user = 'https://bugs.python.org/LCatro'bugs.python.org fields:
activity = <Date 2019-12-31.04:16:45.104>
actor = 'pablogsal'
assignee = 'none'
closed = True
closed_date = <Date 2019-12-31.04:16:45.105>
closer = 'pablogsal'
components = ['Interpreter Core']
creation = <Date 2019-10-25.13:25:50.889>
creator = 'LCatro'
dependencies = []
files = []
hgrepos = []
issue_num = 38588
keywords = ['patch']
message_count = 18.0
messages = ['355366', '355367', '355514', '359023', '359025', '359076', '359077', '359078', '359079', '359080', '359082', '359083', '359087', '359088', '359090', '359094', '359095', '359096']
nosy_count = 5.0
nosy_names = ['methane', 'serhiy.storchaka', 'LCatro', 'corona10', 'pablogsal']
pr_nums = ['17734', '17764', '17765', '17766']
priority = 'normal'
resolution = 'fixed'
stage = 'resolved'
status = 'closed'
superseder = None
type = 'crash'
url = 'https://bugs.python.org/issue38588'
versions = ['Python 2.7', 'Python 3.7', 'Python 3.8', 'Python 3.9']Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
3.7 (EOL)end of lifeend of life3.8 (EOL)end of lifeend of life3.9 (EOL)end of lifeend of lifeinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)type-crashA hard crash of the interpreter, possibly with a core dumpA hard crash of the interpreter, possibly with a core dump
Activity
LCatro commentedon Oct 25, 2019
Code :
The varanit bval forget call Py_INCREF to add reference in dict_equal()
PoC 1 :
Crash Detail :
(gdb) run ../python_poc_info/dict_poc_1.py
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/fuzzing/Desktop/Python-3.8.0/python ../python_poc_info/dict_poc_1.py
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Program received signal SIGSEGV, Segmentation fault.
0x000000000046e445 in do_richcompare (v=v@entry=0x7ffff7e767d0, w=w@entry=0x7ffff6dd88c0, op=op@entry=2)
at Objects/object.c:725
725 if (!checked_reverse_op && (f = w->ob_type->tp_richcompare) != NULL) {
======
Code :
The varanit wl->ob_item[i] forget call Py_INCREF to add reference in list_richcompare()
PoC 2 :
Crash Detail :
(gdb) run ../python_poc_info/list_poc_1.py
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/fuzzing/Desktop/Python-3.8.0/python ../python_poc_info/list_poc_1.py
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Program received signal SIGSEGV, Segmentation fault.
0x000000000044bd07 in long_richcompare (self=0x961200 <small_ints+192>, other=0x7ffff7e767d0, op=2)
at Objects/longobject.c:3083
3083 CHECK_BINOP(self, other);
======
Code :
The varanit PyList_GET_ITEM(a, i) forget call Py_INCREF to add reference in list_contains()
PoC 3 :
Crash Detail :
(gdb) run ../python_poc_info/list_poc_2.py
Starting program: /home/fuzzing/Desktop/Python-3.8.0/python ../python_poc_info/list_poc_2.py
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Program received signal SIGSEGV, Segmentation fault.
0x000000000046e445 in do_richcompare (v=v@entry=0x7ffff7e766e0, w=w@entry=0x7ffff6dd88c0, op=op@entry=2)
at Objects/object.c:725
725 if (!checked_reverse_op && (f = w->ob_type->tp_richcompare) != NULL) {
serhiy-storchaka commentedon Oct 25, 2019
Thank you for your investigation LCatro! Do you mind to create a pull request?
LCatro commentedon Oct 28, 2019
Sure ,but how can i pull my fix code ?
methane commentedon Dec 30, 2019
Would you benchmark the performance?
How about calling Py_INCREF and Py_DECREF in PyObject_RichCompare or do_richcompare?
It is safer than checking all caller of the PyObject_RichCompare and PyObject_RichCompareBool.
And it would be faster when PyObject_RichCompareBool is called with v == w and op == Py_EQ.
methane commentedon Dec 30, 2019
If we can not add INCREF and DECREF in the PyObject_RichCompare, we can add v == w check in the caller side.
pablogsal commentedon Dec 31, 2019
New changeset 2d5bf56 by Pablo Galindo (Dong-hee Na) in branch 'master':
bpo-38588: Fix possible crashes in dict and list when calling PyObject_RichCompareBool (GH-17734)
2d5bf56
pablogsal commentedon Dec 31, 2019
Apologies, I had missed this suggestion before merging the PR :(
If we decide to add the check to PyObject_RichCompare or do_richcompare we should also adapt the fix for https://bugs.python.org/issue38610
methane commentedon Dec 31, 2019
master : Mean +- std dev: 276 ns +- 1 ns
patched: Mean +- std dev: 572 ns +- 3 ns
This makes list comparison 2x slower.
pablogsal commentedon Dec 31, 2019
Would you like to revert PR 17734? Calling Py_INCREF and Py_DECREF in PyObject_RichCompare or do_richcompare will take the same effect, no?
corona10 commentedon Dec 31, 2019
This is affected by PR 17734? or PyObject_RichCompare patched?
corona10 commentedon Dec 31, 2019
Master
Mean +- std dev: 1.08 us +- 0.02 us
Before PR-17734
Mean +- std dev: 584 ns +- 12 ns
New suggested
.....................
Mean +- std dev: 578 ns +- 14 ns
methane commentedon Dec 31, 2019
Caused by PR 17734.
Moving INCREF and DECREF is a huge change. It is just a future idea to prevent same type of bugs. I think it can not be backported.
To fix this issue with minimum performance regression, I think PR 17766 is the best solution. So no need to revert PR 17734.
pablogsal commentedon Dec 31, 2019
Now I am wondering how many other APIs are affected by the same pattern other than PyObject_RichCompareBool....
Thanks for the quick fix and the analysis. I reviewed PR 17734.
pablogsal commentedon Dec 31, 2019
Sorry, I meant that I reviewed PR 17766.
methane commentedon Dec 31, 2019
New changeset dfef986 by Inada Naoki in branch 'master':
bpo-38588: Optimize list comparison. (GH-17766)
dfef986
pablogsal commentedon Dec 31, 2019
New changeset 53f11ba by Pablo Galindo (Dong-hee Na) in branch '3.7':
[3.7] bpo-38588: Fix possible crashes in dict and list when calling P… (GH-17765)
53f11ba
pablogsal commentedon Dec 31, 2019
New changeset 2ee8791 by Pablo Galindo (Dong-hee Na) in branch '3.8':
[3.8] bpo-38588: Fix possible crashes in dict and list when calling P… (GH-17764)
2ee8791
pablogsal commentedon Dec 31, 2019
Closing this for now, let's open another issue if we plan to discuss calling Py_INCREF and Py_DECREF in PyObject_RichCompare or do_richcompare in the future.
Thanks to everyone involved!