Skip to content

Commit 8d472d2

Browse files
authored
Merge branch 'main' into gh-142867-fix-trace-count-missing-lines
2 parents 27aecaf + b9a4806 commit 8d472d2

16 files changed

+106
-6
lines changed

Doc/library/base64.rst

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,14 +267,20 @@ Refer to the documentation of the individual functions for more information.
267267
.. versionadded:: 3.4
268268

269269

270-
.. function:: z85encode(s)
270+
.. function:: z85encode(s, pad=False)
271271

272272
Encode the :term:`bytes-like object` *s* using Z85 (as used in ZeroMQ)
273273
and return the encoded :class:`bytes`. See `Z85 specification
274274
<https://rfc.zeromq.org/spec/32/>`_ for more information.
275275

276+
If *pad* is true, the input is padded with ``b'\0'`` so its length is a
277+
multiple of 4 bytes before encoding.
278+
276279
.. versionadded:: 3.13
277280

281+
.. versionchanged:: next
282+
The *pad* parameter was added.
283+
278284

279285
.. function:: z85decode(s)
280286

Lib/base64.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -508,9 +508,9 @@ def b85decode(b):
508508
)
509509
_z85_encode_translation = bytes.maketrans(_b85alphabet, _z85alphabet)
510510

511-
def z85encode(s):
511+
def z85encode(s, pad=False):
512512
"""Encode bytes-like object b in z85 format and return a bytes object."""
513-
return b85encode(s).translate(_z85_encode_translation)
513+
return b85encode(s, pad).translate(_z85_encode_translation)
514514

515515
def z85decode(s):
516516
"""Decode the z85-encoded bytes-like object or ASCII string b

Lib/test/test_base64.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,7 @@ def test_z85encode(self):
665665

666666
tests = {
667667
b'': b'',
668+
b'\x86\x4F\xD2\x6F\xB5\x59\xF7\x5B': b'HelloWorld',
668669
b'www.python.org': b'CxXl-AcVLsz/dgCA+t',
669670
bytes(range(255)): b"""009c61o!#m2NH?C3>iWS5d]J*6CRx17-skh9337x"""
670671
b"""ar.{NbQB=+c[cR@eg&FcfFLssg=mfIi5%2YjuU>)kTv.7l}6Nnnj=AD"""
@@ -840,6 +841,21 @@ def test_b85_padding(self):
840841
eq(base64.b85decode(b'czAet'), b"xxxx")
841842
eq(base64.b85decode(b'czAetcmMzZ'), b"xxxxx\x00\x00\x00")
842843

844+
def test_z85_padding(self):
845+
eq = self.assertEqual
846+
847+
eq(base64.z85encode(b"x", pad=True), b'CMmZz')
848+
eq(base64.z85encode(b"xx", pad=True), b'CZ6h*')
849+
eq(base64.z85encode(b"xxx", pad=True), b'CZaDk')
850+
eq(base64.z85encode(b"xxxx", pad=True), b'CZaET')
851+
eq(base64.z85encode(b"xxxxx", pad=True), b'CZaETCMmZz')
852+
853+
eq(base64.z85decode(b'CMmZz'), b"x\x00\x00\x00")
854+
eq(base64.z85decode(b'CZ6h*'), b"xx\x00\x00")
855+
eq(base64.z85decode(b'CZaDk'), b"xxx\x00")
856+
eq(base64.z85decode(b'CZaET'), b"xxxx")
857+
eq(base64.z85decode(b'CZaETCMmZz'), b"xxxxx\x00\x00\x00")
858+
843859
def test_a85decode_errors(self):
844860
illegal = (set(range(32)) | set(range(118, 256))) - set(b' \t\n\r\v')
845861
for c in illegal:

Lib/test/test_collections.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2135,6 +2135,19 @@ def test_basics(self):
21352135
self.assertEqual(c.setdefault('e', 5), 5)
21362136
self.assertEqual(c['e'], 5)
21372137

2138+
def test_update_reentrant_add_clears_counter(self):
2139+
c = Counter()
2140+
key = object()
2141+
2142+
class Evil(int):
2143+
def __add__(self, other):
2144+
c.clear()
2145+
return NotImplemented
2146+
2147+
c[key] = Evil()
2148+
c.update([key])
2149+
self.assertEqual(c[key], 1)
2150+
21382151
def test_init(self):
21392152
self.assertEqual(list(Counter(self=42).items()), [('self', 42)])
21402153
self.assertEqual(list(Counter(iterable=42).items()), [('iterable', 42)])

Lib/test/test_ctypes/test_struct_fields.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,21 @@ class S(Structure):
130130
self.check_struct(S)
131131
self.assertEqual(S.largeField.bit_size, size * 8)
132132

133+
def test_bitfield_overflow_error_message(self):
134+
with self.assertRaisesRegex(
135+
ValueError,
136+
r"bit field 'x' overflows its type \(2 \+ 7 > 8\)",
137+
):
138+
CField(
139+
name="x",
140+
type=c_byte,
141+
byte_size=1,
142+
byte_offset=0,
143+
index=0,
144+
_internal_use=True,
145+
bit_size=7,
146+
bit_offset=2,
147+
)
133148

134149
# __set__ and __get__ should raise a TypeError in case their self
135150
# argument is not a ctype instance.

Lib/test/test_free_threading/test_gc.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,38 @@ def mutator_thread():
6262
with threading_helper.start_threads(gcs + mutators):
6363
pass
6464

65+
def test_freeze_object_in_brc_queue(self):
66+
# GH-142975: Freezing objects in the BRC queue could result in some
67+
# objects having a zero refcount without being deallocated.
68+
69+
class Weird:
70+
# We need a destructor to trigger the check for object resurrection
71+
def __del__(self):
72+
pass
73+
74+
# This is owned by the main thread, so the subthread will have to increment
75+
# this object's reference count.
76+
weird = Weird()
77+
78+
def evil():
79+
gc.freeze()
80+
81+
# Decrement the reference count from this thread, which will trigger the
82+
# slow path during resurrection and add our weird object to the BRC queue.
83+
nonlocal weird
84+
del weird
85+
86+
# Collection will merge the object's reference count and make it zero.
87+
gc.collect()
88+
89+
# Unfreeze the object, making it visible to the GC.
90+
gc.unfreeze()
91+
gc.collect()
92+
93+
thread = Thread(target=evil)
94+
thread.start()
95+
thread.join()
96+
6597

6698
if __name__ == "__main__":
6799
unittest.main()

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,7 @@ Lisandro Dalcin
418418
Darren Dale
419419
Andrew Dalke
420420
Lars Damerow
421+
Hauke Dämpfling
421422
Evan Dandrea
422423
Eric Daniel
423424
Scott David Daniels
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix crash after unfreezing all objects tracked by the garbage collector on
2+
the :term:`free threaded <free threading>` build.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix a potential use-after-free in :meth:`collections.Counter.update` when user code
2+
mutates the Counter during an update.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add padding support to :func:`base64.z85encode` via the ``pad`` parameter.

0 commit comments

Comments
 (0)