Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
2a95219b
Commit
2a95219b
authored
May 20, 2016
by
Serhiy Storchaka
Browse files
Options
Browse Files
Download
Plain Diff
Issue #26168: Fixed possible refleaks in failing Py_BuildValue() with the "N"
format unit.
parents
da23056a
13e602ea
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
171 additions
and
53 deletions
+171
-53
Lib/test/test_capi.py
Lib/test/test_capi.py
+3
-0
Misc/NEWS
Misc/NEWS
+3
-0
Modules/_testcapimodule.c
Modules/_testcapimodule.c
+95
-0
Python/modsupport.c
Python/modsupport.c
+70
-53
No files found.
Lib/test/test_capi.py
View file @
2a95219b
...
...
@@ -238,6 +238,9 @@ class CAPITest(unittest.TestCase):
'return_result_with_error.* '
'returned a result with an error set'
)
def
test_buildvalue_N
(
self
):
_testcapi
.
test_buildvalue_N
()
@
unittest
.
skipUnless
(
threading
,
'Threading required for this test.'
)
class
TestPendingCalls
(
unittest
.
TestCase
):
...
...
Misc/NEWS
View file @
2a95219b
...
...
@@ -41,6 +41,9 @@ Release date: 2016-05-16
Core
and
Builtins
-----------------
-
Issue
#
26168
:
Fixed
possible
refleaks
in
failing
Py_BuildValue
()
with
the
"N"
format
unit
.
-
Issue
#
26991
:
Fix
possible
refleak
when
creating
a
function
with
annotations
.
-
Issue
#
27039
:
Fixed
bytearray
.
remove
()
for
values
greater
than
127.
Based
on
...
...
Modules/_testcapimodule.c
View file @
2a95219b
...
...
@@ -872,6 +872,100 @@ test_L_code(PyObject *self)
#endif
/* ifdef HAVE_LONG_LONG */
static
PyObject
*
return_none
(
void
*
unused
)
{
Py_RETURN_NONE
;
}
static
PyObject
*
raise_error
(
void
*
unused
)
{
PyErr_SetNone
(
PyExc_ValueError
);
return
NULL
;
}
static
int
test_buildvalue_N_error
(
const
char
*
fmt
)
{
PyObject
*
arg
,
*
res
;
arg
=
PyList_New
(
0
);
if
(
arg
==
NULL
)
{
return
-
1
;
}
Py_INCREF
(
arg
);
res
=
Py_BuildValue
(
fmt
,
return_none
,
NULL
,
arg
);
if
(
res
==
NULL
)
{
return
-
1
;
}
Py_DECREF
(
res
);
if
(
Py_REFCNT
(
arg
)
!=
1
)
{
PyErr_Format
(
TestError
,
"test_buildvalue_N: "
"arg was not decrefed in successful "
"Py_BuildValue(
\"
%s
\"
)"
,
fmt
);
return
-
1
;
}
Py_INCREF
(
arg
);
res
=
Py_BuildValue
(
fmt
,
raise_error
,
NULL
,
arg
);
if
(
res
!=
NULL
||
!
PyErr_Occurred
())
{
PyErr_Format
(
TestError
,
"test_buildvalue_N: "
"Py_BuildValue(
\"
%s
\"
) didn't complain"
,
fmt
);
return
-
1
;
}
PyErr_Clear
();
if
(
Py_REFCNT
(
arg
)
!=
1
)
{
PyErr_Format
(
TestError
,
"test_buildvalue_N: "
"arg was not decrefed in failed "
"Py_BuildValue(
\"
%s
\"
)"
,
fmt
);
return
-
1
;
}
Py_DECREF
(
arg
);
return
0
;
}
static
PyObject
*
test_buildvalue_N
(
PyObject
*
self
,
PyObject
*
noargs
)
{
PyObject
*
arg
,
*
res
;
arg
=
PyList_New
(
0
);
if
(
arg
==
NULL
)
{
return
NULL
;
}
Py_INCREF
(
arg
);
res
=
Py_BuildValue
(
"N"
,
arg
);
if
(
res
==
NULL
)
{
return
NULL
;
}
if
(
res
!=
arg
)
{
return
raiseTestError
(
"test_buildvalue_N"
,
"Py_BuildValue(
\"
N
\"
) returned wrong result"
);
}
if
(
Py_REFCNT
(
arg
)
!=
2
)
{
return
raiseTestError
(
"test_buildvalue_N"
,
"arg was not decrefed in Py_BuildValue(
\"
N
\"
)"
);
}
Py_DECREF
(
res
);
Py_DECREF
(
arg
);
if
(
test_buildvalue_N_error
(
"O&N"
)
<
0
)
return
NULL
;
if
(
test_buildvalue_N_error
(
"(O&N)"
)
<
0
)
return
NULL
;
if
(
test_buildvalue_N_error
(
"[O&N]"
)
<
0
)
return
NULL
;
if
(
test_buildvalue_N_error
(
"{O&N}"
)
<
0
)
return
NULL
;
if
(
test_buildvalue_N_error
(
"{()O&(())N}"
)
<
0
)
return
NULL
;
Py_RETURN_NONE
;
}
static
PyObject
*
get_args
(
PyObject
*
self
,
PyObject
*
args
)
{
...
...
@@ -3861,6 +3955,7 @@ static PyMethodDef TestMethods[] = {
{
"test_pep3118_obsolete_write_locks"
,
(
PyCFunction
)
test_pep3118_obsolete_write_locks
,
METH_NOARGS
},
#endif
{
"getbuffer_with_null_view"
,
getbuffer_with_null_view
,
METH_O
},
{
"test_buildvalue_N"
,
test_buildvalue_N
,
METH_NOARGS
},
{
"get_args"
,
get_args
,
METH_VARARGS
},
{
"get_kwargs"
,
(
PyCFunction
)
get_kwargs
,
METH_VARARGS
|
METH_KEYWORDS
},
{
"getargs_tuple"
,
getargs_tuple
,
METH_VARARGS
},
...
...
Python/modsupport.c
View file @
2a95219b
...
...
@@ -63,48 +63,84 @@ static PyObject *do_mkdict(const char**, va_list *, int, int, int);
static
PyObject
*
do_mkvalue
(
const
char
**
,
va_list
*
,
int
);
static
void
do_ignore
(
const
char
**
p_format
,
va_list
*
p_va
,
int
endchar
,
int
n
,
int
flags
)
{
PyObject
*
v
;
int
i
;
assert
(
PyErr_Occurred
());
v
=
PyTuple_New
(
n
);
for
(
i
=
0
;
i
<
n
;
i
++
)
{
PyObject
*
exception
,
*
value
,
*
tb
,
*
w
;
PyErr_Fetch
(
&
exception
,
&
value
,
&
tb
);
w
=
do_mkvalue
(
p_format
,
p_va
,
flags
);
PyErr_Restore
(
exception
,
value
,
tb
);
if
(
w
!=
NULL
)
{
if
(
v
!=
NULL
)
{
PyTuple_SET_ITEM
(
v
,
i
,
w
);
}
else
{
Py_DECREF
(
w
);
}
}
}
Py_XDECREF
(
v
);
if
(
**
p_format
!=
endchar
)
{
PyErr_SetString
(
PyExc_SystemError
,
"Unmatched paren in format"
);
return
;
}
if
(
endchar
)
++*
p_format
;
}
static
PyObject
*
do_mkdict
(
const
char
**
p_format
,
va_list
*
p_va
,
int
endchar
,
int
n
,
int
flags
)
{
PyObject
*
d
;
int
i
;
int
itemfailed
=
0
;
if
(
n
<
0
)
return
NULL
;
if
((
d
=
PyDict_New
())
==
NULL
)
if
(
n
%
2
)
{
PyErr_SetString
(
PyExc_SystemError
,
"Bad dict format"
);
do_ignore
(
p_format
,
p_va
,
endchar
,
n
,
flags
);
return
NULL
;
}
/* Note that we can't bail immediately on error as this will leak
refcounts on any 'N' arguments. */
if
((
d
=
PyDict_New
())
==
NULL
)
{
do_ignore
(
p_format
,
p_va
,
endchar
,
n
,
flags
);
return
NULL
;
}
for
(
i
=
0
;
i
<
n
;
i
+=
2
)
{
PyObject
*
k
,
*
v
;
int
err
;
k
=
do_mkvalue
(
p_format
,
p_va
,
flags
);
if
(
k
==
NULL
)
{
itemfailed
=
1
;
Py_
INCREF
(
Py_None
);
k
=
Py_None
;
do_ignore
(
p_format
,
p_va
,
endchar
,
n
-
i
-
1
,
flags
)
;
Py_
DECREF
(
d
);
return
NULL
;
}
v
=
do_mkvalue
(
p_format
,
p_va
,
flags
);
if
(
v
==
NULL
)
{
itemfailed
=
1
;
Py_INCREF
(
Py_None
);
v
=
Py_None
;
}
err
=
PyDict_SetItem
(
d
,
k
,
v
);
Py_DECREF
(
k
);
Py_DECREF
(
v
);
if
(
err
<
0
||
itemfailed
)
{
if
(
v
==
NULL
||
PyDict_SetItem
(
d
,
k
,
v
)
<
0
)
{
do_ignore
(
p_format
,
p_va
,
endchar
,
n
-
i
-
2
,
flags
);
Py_DECREF
(
k
);
Py_XDECREF
(
v
);
Py_DECREF
(
d
);
return
NULL
;
}
Py_DECREF
(
k
);
Py_DECREF
(
v
);
}
if
(
d
!=
NULL
&&
**
p_format
!=
endchar
)
{
if
(
**
p_format
!=
endchar
)
{
Py_DECREF
(
d
);
d
=
NULL
;
PyErr_SetString
(
PyExc_SystemError
,
"Unmatched paren in format"
);
return
NULL
;
}
else
if
(
endchar
)
if
(
endchar
)
++*
p_format
;
return
d
;
}
...
...
@@ -114,29 +150,24 @@ do_mklist(const char **p_format, va_list *p_va, int endchar, int n, int flags)
{
PyObject
*
v
;
int
i
;
int
itemfailed
=
0
;
if
(
n
<
0
)
return
NULL
;
v
=
PyList_New
(
n
);
if
(
v
==
NULL
)
return
NULL
;
/* Note that we can't bail immediately on error as this will leak
refcounts on any 'N' arguments. */
v
=
PyList_New
(
n
);
if
(
v
==
NULL
)
{
do_ignore
(
p_format
,
p_va
,
endchar
,
n
,
flags
);
return
NULL
;
}
for
(
i
=
0
;
i
<
n
;
i
++
)
{
PyObject
*
w
=
do_mkvalue
(
p_format
,
p_va
,
flags
);
if
(
w
==
NULL
)
{
itemfailed
=
1
;
Py_
INCREF
(
Py_None
);
w
=
Py_None
;
do_ignore
(
p_format
,
p_va
,
endchar
,
n
-
i
-
1
,
flags
)
;
Py_
DECREF
(
v
);
return
NULL
;
}
PyList_SET_ITEM
(
v
,
i
,
w
);
}
if
(
itemfailed
)
{
/* do_mkvalue() should have already set an error */
Py_DECREF
(
v
);
return
NULL
;
}
if
(
**
p_format
!=
endchar
)
{
Py_DECREF
(
v
);
PyErr_SetString
(
PyExc_SystemError
,
...
...
@@ -153,37 +184,23 @@ do_mktuple(const char **p_format, va_list *p_va, int endchar, int n, int flags)
{
PyObject
*
v
;
int
i
;
int
itemfailed
=
0
;
if
(
n
<
0
)
return
NULL
;
if
((
v
=
PyTuple_New
(
n
))
==
NULL
)
return
NULL
;
/* Note that we can't bail immediately on error as this will leak
refcounts on any 'N' arguments. */
if
((
v
=
PyTuple_New
(
n
))
==
NULL
)
{
do_ignore
(
p_format
,
p_va
,
endchar
,
n
,
flags
);
return
NULL
;
}
for
(
i
=
0
;
i
<
n
;
i
++
)
{
PyObject
*
w
;
if
(
itemfailed
)
{
PyObject
*
exception
,
*
value
,
*
tb
;
PyErr_Fetch
(
&
exception
,
&
value
,
&
tb
);
w
=
do_mkvalue
(
p_format
,
p_va
,
flags
);
PyErr_Restore
(
exception
,
value
,
tb
);
}
else
{
w
=
do_mkvalue
(
p_format
,
p_va
,
flags
);
}
PyObject
*
w
=
do_mkvalue
(
p_format
,
p_va
,
flags
);
if
(
w
==
NULL
)
{
itemfailed
=
1
;
Py_
INCREF
(
Py_None
);
w
=
Py_None
;
do_ignore
(
p_format
,
p_va
,
endchar
,
n
-
i
-
1
,
flags
)
;
Py_
DECREF
(
v
);
return
NULL
;
}
PyTuple_SET_ITEM
(
v
,
i
,
w
);
}
if
(
itemfailed
)
{
/* do_mkvalue() should have already set an error */
Py_DECREF
(
v
);
return
NULL
;
}
if
(
**
p_format
!=
endchar
)
{
Py_DECREF
(
v
);
PyErr_SetString
(
PyExc_SystemError
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment