[issue35842] A potential bug about use of uninitialised variable

2019-01-28 Thread rongxin


New submission from rongxin :

In the source file mmapmodule.c, the function mmap_subscript contains a 
potential bug about the use of uninitialised variable.


mmapmodule.c:

764 static PyObject *
765 mmap_subscript(mmap_object *self, PyObject *item)
766 {
...
else if (PySlice_Check(item)) {
782Py_ssize_t start, stop, step, slicelen;
783
784if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
785return NULL;
786}
787slicelen = PySlice_AdjustIndices(self->size, &start, &stop, step);
 ...

In Line 782 of the file mmapmodule.c, the variable stop is not initialised and 
will be passed to the function PySlice_Unpack as the third parameter. Inside 
the function, it is likely that stop is not initialised. Please see the 
following code. 

sliceobject.c:
196 int
197 PySlice_Unpack(PyObject *_r,
198   Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
199 {
...
231if (r->stop == Py_None) {
232*stop = *step < 0 ? PY_SSIZE_T_MIN : PY_SSIZE_T_MAX;
233}
234else {
235if (!_PyEval_SliceIndex(r->stop, stop)) return -1;
236}


The third parameter **stop** may be changed at line 232 or 235. However, at 
Line 235, it is still likely that **stop** is not initialised at Line 235 where 
**stop** is passed as the second parameter. Note that, at Line 235, we only 
know r->stop!=Py_None. The following is the code snippet of the function 
_PyEval_SliceIndex.


ceval.c:
4718 int
4719 _PyEval_SliceIndex(PyObject *v, Py_ssize_t *pi)
4720 {
4721 if (v != Py_None) {
4722 Py_ssize_t x;
4723 if (PyIndex_Check(v)) {
4724 x = PyNumber_AsSsize_t(v, NULL);
4725 if (x == -1 && PyErr_Occurred())
4726 return 0;
4727 }
4728 else {
4729 PyErr_SetString(PyExc_TypeError,
4730 "slice indices must be integers or "
4731 "None or have an __index__ method");
4732 return 0;
4733 }
4734 *pi = x;
4735 }
4736return 1;
4737 }

As we can see, it is likely that when the third parameter v can be NULL, then 
the function _PyEval_SliceIndex will return 1. In the caller function 
PySlice_Unpack, at Line 235, the condition **if (!_PyEval_SliceIndex(r->stop, 
stop))** is not satisfied, and thus it will go to Line 238 which returns 0. In 
the caller function mmap_subscript in the file mmapmodule.c, at Line 784, since 
the return value is 0, and thus the path condition **PySlice_Unpack(item, 
&start, &stop, &step) < 0** is not satisfied. It will continue to execute the 
Line 787. The uninitialised variable **stop** again will be passed to the 
function PySlice_AdjustIndices as the third parameter. **stop** then will be 
dereferenced without initialisation. Please see the following.

sliceobject.c:
241 Py_ssize_t
242 PySlice_AdjustIndices(Py_ssize_t length,
243  Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t step)
...
260 if (*stop < 0) {
261*stop += length;
...

--
messages: 334466
nosy: wurongxin1987
priority: normal
severity: normal
status: open
title: A potential bug about use of uninitialised variable
type: security
versions: Python 3.8

___
Python tracker 
<https://bugs.python.org/issue35842>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue35842] A potential bug about use of uninitialised variable

2019-01-28 Thread rongxin


rongxin  added the comment:

BTW, if this bug is true, there is a similar code snippet in the same file.
mmapmodule.c:
845 static int
846 mmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value)
847 {
...
888else if (PySlice_Check(item)) {
889Py_ssize_t start, stop, step, slicelen;
890Py_buffer vbuf;
891
892if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
893return -1;
894}
895slicelen = PySlice_AdjustIndices(self->size, &start, &stop, step);

--

___
Python tracker 
<https://bugs.python.org/issue35842>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue35842] A potential bug about use of uninitialised variable

2019-01-28 Thread rongxin


rongxin  added the comment:

Hi, Josh Rosenberg. As you mentioned PySlice_New (which is ultimately 
responsible for all slice construction) explicitly replaces any argument of 
NULL with Py_None, I am not sure whether this is always true r->stop cannot be 
NULL. I detected this bug using the code of Python 2.7.15. The implementation 
of _PyEval_SliceIndex is shown as followings. Please read the comments of this 
functions, and it is possible that v would be NULL. I wonder whether your 
assumption r->stop cannot be NULL will be broken in Python 2.7.15



/* Extract a slice index from a PyInt or PyLong or an object with the
   nb_index slot defined, and store in *pi.
   Silently reduce values larger than PY_SSIZE_T_MAX to PY_SSIZE_T_MAX,
   and silently boost values less than PY_SSIZE_T_MIN to PY_SSIZE_T_MIN.
   Return 0 on error, 1 on success.
*/
/* Note:  If v is NULL, return success without storing into *pi.  This
   is because_PyEval_SliceIndex() is called by apply_slice(), which can be
   called by the SLICE opcode with v and/or w equal to NULL.
*/
int
_PyEval_SliceIndex(PyObject *v, Py_ssize_t *pi)
{
if (v != NULL && v != Py_None) {
Py_ssize_t x;
if (PyInt_Check(v)) {
/* XXX(nnorwitz): I think PyInt_AS_LONG is correct,
   however, it looks like it should be AsSsize_t.
   There should be a comment here explaining why.
*/
x = PyInt_AS_LONG(v);
}
else if (PyIndex_Check(v)) {
x = PyNumber_AsSsize_t(v, NULL);
if (x == -1 && PyErr_Occurred())
return 0;
}
else {
PyErr_SetString(PyExc_TypeError,
"slice indices must be integers or "
"None or have an __index__ method");
return 0;
}
*pi = x;
}
return 1;
}

--

___
Python tracker 
<https://bugs.python.org/issue35842>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue35842] A potential bug about use of uninitialised variable

2019-01-28 Thread rongxin


rongxin  added the comment:

I think this bug is valid at least in Python 2.7, as I mentioned the 
implementation of _PyEval_SliceIndex is different from the one in Python 3.8. 
The condition " if (v != NULL && v != Py_None) " will bypass the NULL pointer 
dereference. Would you please check this again? Thanks.

--
status: closed -> open
versions: +Python 2.7 -Python 3.8

___
Python tracker 
<https://bugs.python.org/issue35842>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue35842] A potential bug about use of uninitialised variable

2019-01-28 Thread rongxin


Change by rongxin :


--
resolution: not a bug -> 

___
Python tracker 
<https://bugs.python.org/issue35842>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue35842] A potential bug about use of uninitialised variable

2019-01-29 Thread rongxin


rongxin  added the comment:

Josh Rosenberg, thanks for your useful comments.

--

___
Python tracker 
<https://bugs.python.org/issue35842>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com