Skip to content

Conversation

@vstinner
Copy link
Member

@vstinner vstinner commented 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
Copy link
Member Author

@gpshead @serhiy-storchaka @methane: Would you mind to review my list_resize() fix?

@serhiy-storchaka
Copy link
Member

serhiy-storchaka commented Sep 28, 2022

There is no integer overflow here.

@serhiy-storchaka
Copy link
Member

Or rather there should not be integer overflow. Unsigned sizes are intentionally used to avoid integer overflow.

@gpshead
Copy link
Member

gpshead commented Sep 28, 2022

There is no integer overflow here.

Clarification: are you suggesting there was never a problem in the first place or that this change looks good?

A sufficiently large newsize previously would have caused num_allocated_bytes passed to realloc to be too small.

@serhiy-storchaka
Copy link
Member

At first glance, I saw that the existing code was already written to protect against integer overflow, so an explicit check seemed redundant. Then I read the issue and saw that it only protected against some cases of integer overflows. So the code in this PR is correct and necessary.

@vstinner
Copy link
Member Author

See #97616 (comment) for an explanation of the integer overflow.

@vstinner
Copy link
Member Author

Explicitly cast PY_SSIZE_T_MAX to size_t

I hate implicit conversion between signed and unsigned, it commonly emits compiler warnings. I prefer to only work on unsigned numbers there.

@vstinner
Copy link
Member Author

I ran the added test on the main branch: it does crash as expected.

vstinner@mona$ ./python -m test -v test_list -m test_list_resize_overflow
...
test_list_resize_overflow (test.test_list.ListTest.test_list_resize_overflow) ... Fatal Python error: Segmentation fault

Current thread 0x00007faeb98da740 (most recent call first):
  File "/home/vstinner/python/main/Lib/test/test_list.py", line 110 in test_list_resize_overflow
  ...

It only crashs on the second test (lst *= size): tuple.__imul__() works in-place and so calls list_resize().

        size = ((2 ** (tuple.__itemsize__ * 8) - 1) // 2)
        with self.assertRaises((MemoryError, OverflowError)):
            lst * size
        with self.assertRaises((MemoryError, OverflowError)):
            lst *= size   # <=== HERE

The first one (lst * size) doesn't crash: tuple.__mul__() creates a new list, it doesn't call list_resize().

I prefer to test both cases.

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
Copy link
Member Author

Fix multiplying a list by an integer (list * int)

Well, the bug is on list *= int, I fixed the doc.

@vstinner vstinner merged commit a5f092f into python:main Sep 28, 2022
@miss-islington
Copy link
Contributor

Thanks @vstinner for the PR 🌮🎉.. I'm working now to backport this PR to: 3.7, 3.8, 3.9, 3.10, 3.11.
🐍🍒⛏🤖

@vstinner vstinner deleted the list_resize branch September 28, 2022 22:07
@bedevere-bot bedevere-bot removed the needs backport to 3.11 only security fixes label Sep 28, 2022
@bedevere-bot
Copy link

GH-97625 is a backport of this pull request to the 3.11 branch.

@bedevere-bot
Copy link

GH-97626 is a backport of this pull request to the 3.10 branch.

@bedevere-bot
Copy link

GH-97627 is a backport of this pull request to the 3.9 branch.

@bedevere-bot
Copy link

GH-97628 is a backport of this pull request to the 3.8 branch.

@bedevere-bot
Copy link

GH-97629 is a backport of this pull request to the 3.7 branch.

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request 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 a5f092f)

Co-authored-by: Victor Stinner <[email protected]>
miss-islington pushed a commit to miss-islington/cpython that referenced this pull request 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 a5f092f)

Co-authored-by: Victor Stinner <[email protected]>
miss-islington pushed a commit to miss-islington/cpython that referenced this pull request 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 a5f092f)

Co-authored-by: Victor Stinner <[email protected]>
miss-islington pushed a commit to miss-islington/cpython that referenced this pull request 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 a5f092f)

Co-authored-by: Victor Stinner <[email protected]>
miss-islington pushed a commit to miss-islington/cpython that referenced this pull request 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 a5f092f)

Co-authored-by: Victor Stinner <[email protected]>
miss-islington added a commit that referenced this pull request 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 <[email protected]>
miss-islington added a commit that referenced this pull request 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 <[email protected]>
ambv pushed a commit that referenced this pull request Oct 4, 2022
…H-97627)

gh-97616: list_resize() checks for integer overflow (GH-97617)

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 <[email protected]>
ambv pushed a commit that referenced this pull request Oct 4, 2022
…H-97628)

gh-97616: list_resize() checks for integer overflow (GH-97617)

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 <[email protected]>
ambv pushed a commit that referenced this pull request Oct 5, 2022
…97629)

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 <[email protected]>
@lazka
Copy link
Contributor

lazka commented Oct 7, 2022

If such overflow checks are common in CPython you could consider using macros like in glib for example: https://developer-old.gnome.org/glib/stable/glib-Bounds-checked-integer-arithmetic.html

pablogsal pushed a commit that referenced this pull request Oct 24, 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 <[email protected]>
pablogsal pushed a commit that referenced this pull request Oct 24, 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 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type-security A security issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants