diff options
| author | Angus Gratton <angus@redyak.com.au> | 2024-02-13 09:24:36 +1100 |
|---|---|---|
| committer | Damien George <damien@micropython.org> | 2024-04-22 11:50:52 +1000 |
| commit | 4bed614e707c0644c06e117f848fa12605c711cd (patch) | |
| tree | 5deed37ec215eeff1d7eb540c6b8f9ae51d1725f /tests/basics | |
| parent | ce491ab0d168a8278062e1fc7ebed3ca47ab89d2 (diff) | |
py/objarray: Fix use-after-free if extending a bytearray from itself.
Two cases, one assigning to a slice.
Closes https://github.com/micropython/micropython/issues/13283
Second is extending a slice from itself, similar logic.
In both cases the problem occurs when m_renew causes realloc to move the
buffer, leaving a dangling pointer behind.
There are more complex and hard to fix cases when either argument is a
memoryview into the buffer, currently resizing to a new address breaks
memoryviews into that object.
Reproducing this bug and confirming the fix was done by running the unix
port under valgrind with GC-aware extensions.
Note in default configurations with GIL this bug exists but has no impact
(the free buffer won't be reused while the function is still executing, and
is no longer referenced after it returns).
Signed-off-by: Angus Gratton <angus@redyak.com.au>
Diffstat (limited to 'tests/basics')
| -rw-r--r-- | tests/basics/bytearray_add.py | 9 | ||||
| -rw-r--r-- | tests/basics/bytearray_add_self.py | 8 | ||||
| -rw-r--r-- | tests/basics/bytearray_add_self.py.exp | 1 | ||||
| -rw-r--r-- | tests/basics/bytearray_slice_assign.py | 18 |
4 files changed, 29 insertions, 7 deletions
diff --git a/tests/basics/bytearray_add.py b/tests/basics/bytearray_add.py index a7e2b5737..1f30a3b74 100644 --- a/tests/basics/bytearray_add.py +++ b/tests/basics/bytearray_add.py @@ -15,4 +15,11 @@ print(b) # this inplace add tests the code when the buffer doesn't need to be increased b = bytearray() -b += b'' +b += b"" + +# extend a bytearray from itself +b = bytearray(b"abcdefgh") +for _ in range(4): + c = bytearray(b) # extra allocation, as above + b.extend(b) +print(b) diff --git a/tests/basics/bytearray_add_self.py b/tests/basics/bytearray_add_self.py new file mode 100644 index 000000000..94ae8689f --- /dev/null +++ b/tests/basics/bytearray_add_self.py @@ -0,0 +1,8 @@ +# add a bytearray to itself +# This is not supported by CPython as of 3.11.18. + +b = bytearray(b"123456789") +for _ in range(4): + c = bytearray(b) # extra allocation increases chance 'b' has to relocate + b += b +print(b) diff --git a/tests/basics/bytearray_add_self.py.exp b/tests/basics/bytearray_add_self.py.exp new file mode 100644 index 000000000..5ef948157 --- /dev/null +++ b/tests/basics/bytearray_add_self.py.exp @@ -0,0 +1 @@ +bytearray(b'123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789') diff --git a/tests/basics/bytearray_slice_assign.py b/tests/basics/bytearray_slice_assign.py index fa7878e10..4de081904 100644 --- a/tests/basics/bytearray_slice_assign.py +++ b/tests/basics/bytearray_slice_assign.py @@ -18,7 +18,7 @@ l = bytearray(x) l[1:3] = bytearray() print(l) l = bytearray(x) -#del l[1:3] +# del l[1:3] print(l) l = bytearray(x) @@ -28,7 +28,7 @@ l = bytearray(x) l[:3] = bytearray() print(l) l = bytearray(x) -#del l[:3] +# del l[:3] print(l) l = bytearray(x) @@ -38,7 +38,7 @@ l = bytearray(x) l[:-3] = bytearray() print(l) l = bytearray(x) -#del l[:-3] +# del l[:-3] print(l) # slice assignment that extends the array @@ -61,8 +61,14 @@ b[1:1] = b"12345" print(b) # Growth of bytearray via slice extension -b = bytearray(b'12345678') -b.append(57) # expand and add a bit of unused space at end of the bytearray +b = bytearray(b"12345678") +b.append(57) # expand and add a bit of unused space at end of the bytearray for i in range(400): - b[-1:] = b'ab' # grow slowly into the unused space + b[-1:] = b"ab" # grow slowly into the unused space +print(len(b), b) + +# Growth of bytearray via slice extension from itself +b = bytearray(b"1234567") +for i in range(3): + b[-1:] = b print(len(b), b) |
