Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[security] list_resize(): integer overflow if newsize is too large #97616

Open
vstinner opened this issue Sep 28, 2022 · 1 comment
Open

[security] list_resize(): integer overflow if newsize is too large #97616

vstinner opened this issue Sep 28, 2022 · 1 comment
Labels
type-bug An unexpected behavior, bug, or error type-security A security issue

Comments

@vstinner
Copy link
Member

vstinner commented Sep 28, 2022

Jordan Limor reported an issue in the C list_resize() function called when a Python list is resized:

When list_resize is hit with the maximum value for a c_ssize_t, the
overallocation strategy causes an overflow in the total allocated bytes.
This results in a call to PyMem_Realloc where the argument is 0 (and one
byte is allocated), but the resulting list's size is set to PY_SSIZE_T_MAX.

Example bug.py:

import sys
import faulthandler; faulthandler.enable()

x=[0]*65
del x[1:]
assert len(x) == 1

print("resize list", flush=True)
max_size = ((2 ** (tuple.__itemsize__ * 8) - 1) // 2)
x *= max_size
print(f"{len(x)=}")
print(f"{sys.getsizeof(x)=}")

# crash on reading uninitizalized memory
print("x[8]=", end="", flush=True)
print(x[8])

Output:

$ python3.10 bug.py 
resize list
Fatal Python error: Segmentation fault

Current thread 0x00007fe16ead0740 (most recent call first):
  File "bug.py", line 10 in <module>
Erreur de segmentation (core dumped)

Tasks

@vstinner vstinner added type-bug An unexpected behavior, bug, or error type-security A security issue labels Sep 28, 2022
@vstinner vstinner changed the title list_resize(): integer overflow if newsize is too large [security] list_resize(): integer overflow if newsize is too large Sep 28, 2022
@vstinner
Copy link
Member Author

vstinner commented Sep 28, 2022

When the bug triggers, list_resize() is called with newsize=9223372036854775807: 2**63-1 (PY_SSIZE_T_MAX).

new_allocated = ((size_t)newsize + (newsize >> 3) + 6) & ~(size_t)3; gives 10376293541461622788.

But (newsize - Py_SIZE(self) > (Py_ssize_t)(new_allocated - newsize)) condition is true, and so new_allocated = ((size_t)newsize + 3) & ~(size_t)3; is computed which gives new_allocated=9223372036854775808 which is PY_SSIZE_T_MAX + 1.

The integer overflow occurs on num_allocated_bytes = new_allocated * sizeof(PyObject *); which gives: num_allocated_bytes=0.

vstinner added a commit to vstinner/cpython that referenced this issue Sep 28, 2022
Fix multiplying a list by an integer (list * int): detect the integer
overflow when the integer is close to the maximum size. Issue
reported by Jordan Limor.
vstinner added a commit to vstinner/cpython that referenced this issue Sep 28, 2022
Fix multiplying a list by an integer (list * int): detect the integer
overflow when the integer is close to the maximum size. Issue
reported by Jordan Limor.

list_resize() now checks for integer overflow before multiplying the
new length by the list item size (sizeof(PyObject*)).
vstinner added a commit to vstinner/cpython that referenced this issue Sep 28, 2022
Fix multiplying a list by an integer (list * int): detect the integer
overflow when the integer is close to the maximum size. Issue
reported by Jordan Limor.

list_resize() now checks for integer overflow before multiplying the
new length by the list item size (sizeof(PyObject*)).
vstinner added a commit to vstinner/cpython that referenced this issue Sep 28, 2022
Fix multiplying a list by an integer (list * int): detect the integer
overflow when the new allocated length is close to the maximum size.
Issue reported by Jordan Limor.

list_resize() now checks for integer overflow before multiplying the
new length by the list item size (sizeof(PyObject*)).
vstinner added a commit to vstinner/cpython that referenced this issue Sep 28, 2022
Fix multiplying a list by an integer (list * int): detect the integer
overflow when the new allocated length is close to the maximum size.
Issue reported by Jordan Limor.

list_resize() now checks for integer overflow before multiplying the
new allocated length by the list item size (sizeof(PyObject*)).
vstinner added a commit to vstinner/cpython that referenced this issue Sep 28, 2022
Fix multiplying a list by an integer (list *= int): detect the
integer overflow when the new allocated length is close to the
maximum size.  Issue reported by Jordan Limor.

list_resize() now checks for integer overflow before multiplying the
new allocated length by the list item size (sizeof(PyObject*)).
miss-islington pushed a commit to miss-islington/cpython that referenced this issue Sep 28, 2022
…7617)

Fix multiplying a list by an integer (list *= int): detect the
integer overflow when the new allocated length is close to the
maximum size.  Issue reported by Jordan Limor.

list_resize() now checks for integer overflow before multiplying the
new allocated length by the list item size (sizeof(PyObject*)).
(cherry picked from commit a5f092f3c469b674b8d9ccbd4e4377230c9ac7cf)

Co-authored-by: Victor Stinner <vstinner@python.org>
miss-islington pushed a commit to miss-islington/cpython that referenced this issue Sep 28, 2022
…7617)

Fix multiplying a list by an integer (list *= int): detect the
integer overflow when the new allocated length is close to the
maximum size.  Issue reported by Jordan Limor.

list_resize() now checks for integer overflow before multiplying the
new allocated length by the list item size (sizeof(PyObject*)).
(cherry picked from commit a5f092f3c469b674b8d9ccbd4e4377230c9ac7cf)

Co-authored-by: Victor Stinner <vstinner@python.org>
miss-islington pushed a commit to miss-islington/cpython that referenced this issue Sep 28, 2022
…7617)

Fix multiplying a list by an integer (list *= int): detect the
integer overflow when the new allocated length is close to the
maximum size.  Issue reported by Jordan Limor.

list_resize() now checks for integer overflow before multiplying the
new allocated length by the list item size (sizeof(PyObject*)).
(cherry picked from commit a5f092f3c469b674b8d9ccbd4e4377230c9ac7cf)

Co-authored-by: Victor Stinner <vstinner@python.org>
miss-islington pushed a commit to miss-islington/cpython that referenced this issue Sep 28, 2022
…7617)

Fix multiplying a list by an integer (list *= int): detect the
integer overflow when the new allocated length is close to the
maximum size.  Issue reported by Jordan Limor.

list_resize() now checks for integer overflow before multiplying the
new allocated length by the list item size (sizeof(PyObject*)).
(cherry picked from commit a5f092f3c469b674b8d9ccbd4e4377230c9ac7cf)

Co-authored-by: Victor Stinner <vstinner@python.org>
miss-islington pushed a commit to miss-islington/cpython that referenced this issue Sep 28, 2022
…7617)

Fix multiplying a list by an integer (list *= int): detect the
integer overflow when the new allocated length is close to the
maximum size.  Issue reported by Jordan Limor.

list_resize() now checks for integer overflow before multiplying the
new allocated length by the list item size (sizeof(PyObject*)).
(cherry picked from commit a5f092f3c469b674b8d9ccbd4e4377230c9ac7cf)

Co-authored-by: Victor Stinner <vstinner@python.org>
vstinner added a commit that referenced this issue Sep 28, 2022
Fix multiplying a list by an integer (list *= int): detect the
integer overflow when the new allocated length is close to the
maximum size.  Issue reported by Jordan Limor.

list_resize() now checks for integer overflow before multiplying the
new allocated length by the list item size (sizeof(PyObject*)).
miss-islington added a commit that referenced this issue Sep 28, 2022
Fix multiplying a list by an integer (list *= int): detect the
integer overflow when the new allocated length is close to the
maximum size.  Issue reported by Jordan Limor.

list_resize() now checks for integer overflow before multiplying the
new allocated length by the list item size (sizeof(PyObject*)).
(cherry picked from commit a5f092f)

Co-authored-by: Victor Stinner <vstinner@python.org>
miss-islington added a commit that referenced this issue Sep 28, 2022
Fix multiplying a list by an integer (list *= int): detect the
integer overflow when the new allocated length is close to the
maximum size.  Issue reported by Jordan Limor.

list_resize() now checks for integer overflow before multiplying the
new allocated length by the list item size (sizeof(PyObject*)).
(cherry picked from commit a5f092f)

Co-authored-by: Victor Stinner <vstinner@python.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type-bug An unexpected behavior, bug, or error type-security A security issue
Projects
None yet
Development

No branches or pull requests

1 participant