Artwork fetch: release the DNS slot if its thread can't start; stricter GIF control blocks

Final review follow-up. A failed Thread.start() leaked a resolver slot (four
failures disabled artwork lookups). GIF graphic-control blocks must have the
fixed 4-byte payload (otherwise dropped) and an image with no pixel data is
rejected.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
saphidandClaude Opus 5.5 committed 2026-09-28 23:48:20 +10:00
1 parent 3b36feff52
commit cb05395280
3 files changed
+31 -3

No files matched your search

+22
View File
@@ -232,6 +232,17 @@ class ArtworkTests(unittest.TestCase):
time.sleep(0.01)
_images._resolvers.release() # the stuck lookups finished and gave their slots back
def test_resolver_slot_released_when_thread_cannot_start(self):
from apk_sources import _images
with patch.object(_images.threading.Thread, 'start', side_effect=RuntimeError("can't start new thread")):
for _ in range(6):
with self.assertRaises(RuntimeError):
_images.get('https://example.org/a.png', deadline=time.monotonic() + 1)
for _ in range(4): # every slot came back
self.assertTrue(_images._resolvers.acquire(blocking=False))
for _ in range(4):
_images._resolvers.release()
def test_deadline_covers_name_resolution(self):
import threading
from apk_sources import _images
@@ -287,6 +298,17 @@ class ArtworkTests(unittest.TestCase):
with self.subTest(cut=cut), self.assertRaises(ValueError):
art.gif_frame(one[:cut])
def test_gif_control_block_and_empty_image(self):
image = self.FRAME[8:] # the image without its graphic control block
head = b'GIF89a' + struct.pack('<HHBBB', 1, 1, 0x80, 0, 0) + b'\xff\xff\xff\x00\x00\x00'
good = b'\x21\xf9\x04\x00\x00\x00\x00\x00'
self.assertEqual(art.gif_frame(head + good + image + b'\x3b'), head + good + image + b'\x3b')
bad = b'\x21\xf9\x02\x00\x00\x00' # wrong payload size: dropped, not passed on
self.assertEqual(art.gif_frame(head + bad + image + b'\x3b'), head + image + b'\x3b')
empty = b'\x2c' + struct.pack('<HHHHB', 0, 0, 1, 1, 0) + b'\x02\x00'
with self.assertRaises(ValueError):
art.gif_frame(head + empty + b'\x3b')
def test_png_variants_left_to_chromium_and_limits(self):
def png(w, h, depth, color, interlace):
return art.PNG + art.chunk(b'IHDR', struct.pack('>IIBBBBB', w, h, depth, color, 0, 0, interlace)) + \