Message242315
# 3617 for (i = 0; i < len; i++) {
# (gdb) print *(PyListObject*)tmp
# $1 = {ob_base = {ob_base = {_ob_next = 0x4056f8f4, _ob_prev = 0x4057329c, ob_refcnt = 2, ob_type = 0x830e1c0 <PyList_Type>},
# ob_size = 1337}, ob_item = 0x8491ae0, allocated = 1432}
# (gdb) n
# 3619 res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
# (gdb) n
# 3620 if (res != 0) goto failed;
# (gdb) print *(PyListObject*)tmp
# $2 = {ob_base = {ob_base = {_ob_next = 0x4056f8f4, _ob_prev = 0x4057329c, ob_refcnt = 2, ob_type = 0x830e1c0 <PyList_Type>},
# ob_size = 1}, ob_item = 0x8491ae0, allocated = 4}
# (gdb) c
# Continuing.
#
# Program received signal SIGSEGV, Segmentation fault.
# 0x080f2c17 in PyObject_GetAttr (v=<unknown at remote 0x405733b4>, name='lineno') at Objects/object.c:872
# 872 if (tp->tp_getattro != NULL)
#
# Objects freed in __getattr__ are used later in the loop above. There are two
# bugs actually. One is the use-after-free and the second is using a stale size
# variable "len" to control the for(...) loop. "body" can be mutated inside
# obj2ast_stmt.
This construct:
for (i = 0; i < len; i++) {
stmt_ty value;
res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
if (res != 0) goto failed;
asdl_seq_SET(body, i, value);
}
is repeated multiple times in multiple obj2ast_ methods. It contains two bugs:
1. tmp[i] isn't protected from deletion inside python code (refcnt is not increased by GET_ITEM),
2. tmp's length can drop below "len" resulting in an OOB read, because the loop counter is static. |
|
Date |
User |
Action |
Args |
2015-05-01 14:10:29 | pkt | set | recipients:
+ pkt |
2015-05-01 14:10:29 | pkt | set | messageid: <1430489429.65.0.587999729774.issue24098@psf.upfronthosting.co.za> |
2015-05-01 14:10:29 | pkt | link | issue24098 messages |
2015-05-01 14:10:29 | pkt | create | |
|