Raise ValueError is XMP data is too long

This commit is contained in:
Andrew Murray 2024-08-05 21:48:36 +10:00
parent 2722cfd72b
commit d49884e40c
2 changed files with 19 additions and 8 deletions

View File

@ -993,11 +993,17 @@ class TestFileJpeg:
def test_save_xmp(self, tmp_path: Path) -> None: def test_save_xmp(self, tmp_path: Path) -> None:
f = str(tmp_path / "temp.jpg") f = str(tmp_path / "temp.jpg")
hopper().save(f, xmp=b"XMP test") im = hopper()
im.save(f, xmp=b"XMP test")
with Image.open(f) as reloaded: with Image.open(f) as reloaded:
assert reloaded.info["xmp"] == b"XMP test" assert reloaded.info["xmp"] == b"XMP test"
im.save(f, xmp=b"1" * 65504)
with pytest.raises(ValueError):
im.save(f, xmp=b"1" * 65505)
@pytest.mark.timeout(timeout=1) @pytest.mark.timeout(timeout=1)
def test_eof(self) -> None: def test_eof(self) -> None:
# Even though this decoder never says that it is finished # Even though this decoder never says that it is finished

View File

@ -746,23 +746,28 @@ def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
extra = info.get("extra", b"") extra = info.get("extra", b"")
MAX_BYTES_IN_MARKER = 65533
xmp = info.get("xmp") xmp = info.get("xmp")
if xmp: if xmp:
size = o16(31 + len(xmp)) overhead_len = 29
max_data_bytes_in_marker = MAX_BYTES_IN_MARKER - overhead_len
if len(xmp) > max_data_bytes_in_marker:
msg = "XMP data is too long"
raise ValueError(msg)
size = o16(2 + overhead_len + len(xmp))
extra += b"\xFF\xE1" + size + b"http://ns.adobe.com/xap/1.0/\x00" + xmp extra += b"\xFF\xE1" + size + b"http://ns.adobe.com/xap/1.0/\x00" + xmp
MAX_BYTES_IN_MARKER = 65533
icc_profile = info.get("icc_profile") icc_profile = info.get("icc_profile")
if icc_profile: if icc_profile:
ICC_OVERHEAD_LEN = 14 overhead_len = 14
MAX_DATA_BYTES_IN_MARKER = MAX_BYTES_IN_MARKER - ICC_OVERHEAD_LEN max_data_bytes_in_marker = MAX_BYTES_IN_MARKER - overhead_len
markers = [] markers = []
while icc_profile: while icc_profile:
markers.append(icc_profile[:MAX_DATA_BYTES_IN_MARKER]) markers.append(icc_profile[:max_data_bytes_in_marker])
icc_profile = icc_profile[MAX_DATA_BYTES_IN_MARKER:] icc_profile = icc_profile[max_data_bytes_in_marker:]
i = 1 i = 1
for marker in markers: for marker in markers:
size = o16(2 + ICC_OVERHEAD_LEN + len(marker)) size = o16(2 + overhead_len + len(marker))
extra += ( extra += (
b"\xFF\xE2" b"\xFF\xE2"
+ size + size