Files
nearology 56c5ee23d3
Verify / test (push) Failing after 2m54s
first commit
2026-11-05 17:31:17 +03:30

59 خطوط
3.0 KiB
Python

"""Decode only bounded, embedded raster assets. Never follow document filenames."""
import base64
import io
import struct
import warnings
import zlib
import olefile
from PIL import Image
from .record_decoder import binary_records, ParseError
MAX_ASSET = 16 * 1024 * 1024
MAX_PIXELS = 16_000_000
Image.MAX_IMAGE_PIXELS = MAX_PIXELS
def asset_name(name): return name.replace('\\', '/').rsplit('/', 1)[-1].casefold()
def read_images(data):
if not data.startswith(olefile.MAGIC): return {}, []
assets, errors = {}, []
try:
with olefile.OleFileIO(io.BytesIO(data)) as ole:
if not ole.exists('Storage'): return assets, errors
raw = ole.openstream('Storage').read()
total = 0
for record in binary_records(raw, 'Storage'):
if not record.binary: continue
payload = base64.b64decode(record.properties['BINARY_BASE64'])
if len(payload) < 6 or payload[0] != 0xd0:
errors.append('Unsupported embedded storage framing'); continue
n = payload[1]
if len(payload) < n+6: raise ParseError('Truncated embedded storage asset')
name = asset_name(payload[2:2+n].decode('cp1252', errors='replace'))
count = struct.unpack_from('<I', payload, 2+n)[0]
if count != len(payload)-6-n: raise ParseError('Invalid embedded compressed size')
decoder = zlib.decompressobj()
raster = decoder.decompress(payload[6+n:], MAX_ASSET+1)
if len(raster) > MAX_ASSET or not decoder.eof or decoder.unused_data:
raise ParseError('Embedded raster exceeds decoding limit or has invalid compression')
total += len(raster)
if total > 32*1024*1024: raise ParseError('Total embedded raster size limit exceeded')
with warnings.catch_warnings():
warnings.simplefilter('error', Image.DecompressionBombWarning)
with Image.open(io.BytesIO(raster)) as source:
if source.width*source.height > MAX_PIXELS: raise ParseError('Embedded raster pixel limit exceeded')
if source.format not in {'PNG','BMP','JPEG','TIFF','GIF'}:
errors.append('Unsupported embedded raster format'); continue
if getattr(source, 'n_frames', 1) != 1:
errors.append('Multi-frame raster skipped'); continue
image = source.convert('RGBA')
output = io.BytesIO(); image.save(output, format='PNG')
png = output.getvalue()
if len(png) > MAX_ASSET: raise ParseError('Converted raster exceeds asset limit')
if name in assets:
errors.append('Ambiguous embedded filename skipped'); assets[name] = None
else: assets[name] = 'data:image/png;base64,' + base64.b64encode(png).decode('ascii')
except Exception as exc:
errors.append('Embedded storage not completely decoded: ' + str(exc)[:160])
return assets, errors