diff --git a/piexif/_webp.py b/piexif/_webp.py index f9cc42e..a47d29a 100644 --- a/piexif/_webp.py +++ b/piexif/_webp.py @@ -1,6 +1,8 @@ import struct +# Define a maximum recursion depth to avoid excessive recursion +MAX_WEBP_CHUNK_RECURSION_DEPTH = 10 def split(data): if data[0:4] != b"RIFF" or data[8:12] != b"WEBP": @@ -92,25 +94,104 @@ def _get_size_from_anmf(chunk): height_minus_one = struct.unpack(" data_length: + break + + # Read the fourcc code (4 bytes) + fourcc = data[offset:offset + 4] + offset += 4 + + # Read the length of the chunk (4 bytes, little-endian) + length = struct.unpack(' data_length: + break + + # Read the chunk data + chunk_data = data[offset:offset + length] + offset += length + + # Append the sub-chunk to the list + sub_chunks.append({ + 'fourcc': fourcc, + 'length_bytes': struct.pack(' MAX_WEBP_CHUNK_RECURSION_DEPTH: + raise RecursionError("Exceeded max allowed recursion depth while processing chunk.") + + nonlocal max_width, max_height if chunk["fourcc"] == b"VP8X": width, height = _get_size_from_vp8x(chunk) + max_width, max_height = update_max_dimensions(max_width, max_height, width, height) elif chunk["fourcc"] == b"VP8 ": width, height = _get_size_from_vp8(chunk) + max_width, max_height = update_max_dimensions(max_width, max_height, width, height) elif chunk["fourcc"] == b"VP8L": is_rgba = _vp8L_contains_alpha(chunk["data"]) if is_rgba: flags[3] = b"1" width, height = _get_size_from_vp8L(chunk) + max_width, max_height = update_max_dimensions(max_width, max_height, width, height) elif chunk["fourcc"] == b"ANMF": + sub_chunks = _get_sub_chunks_from_anmf(chunk) + for sub_chunk in sub_chunks: + process_chunk(sub_chunk, depth=depth + 1) width, height = _get_size_from_anmf(chunk) + max_width, max_height = update_max_dimensions(max_width, max_height, width, height) elif chunk["fourcc"] == b"ICCP": flags[2] = b"1" elif chunk["fourcc"] == b"ALPH": @@ -121,9 +202,12 @@ def set_vp8x(chunks): flags[5] = b"1" elif chunk["fourcc"] == b"ANIM": flags[6] = b"1" - width_minus_one = width - 1 - height_minus_one = height - 1 + for chunk in chunks: + process_chunk(chunk) + + max_width_minus_one = max_width - 1 + max_height_minus_one = max_height - 1 if chunks[0]["fourcc"] == b"VP8X": chunks.pop(0) @@ -131,8 +215,8 @@ def set_vp8x(chunks): length_bytes = b"\x0a\x00\x00\x00" flags_bytes = struct.pack("B", int(b"".join(flags), 2)) padding_bytes = b"\x00\x00\x00" - width_bytes = struct.pack("