mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 21:17:44 +00:00
LibGfx/TIFF: Ensure baseline tags presence before decoding
This allows us to reject invalid images before trying to decode them. The spec requires more tag to be present[1] but as we don't use them for decoding I don't see the point. [1] - XResolution, YResolution and ResolutionUnit
This commit is contained in:
parent
ec2b4c271f
commit
a31b988473
2 changed files with 26 additions and 10 deletions
|
@ -96,7 +96,7 @@ class ExtraSample(EnumWithExportName):
|
|||
UnassociatedAlpha = 2
|
||||
|
||||
|
||||
tag_fields = ['id', 'types', 'counts', 'default', 'name', 'associated_enum']
|
||||
tag_fields = ['id', 'types', 'counts', 'default', 'name', 'associated_enum', 'is_required']
|
||||
|
||||
Tag = namedtuple(
|
||||
'Tag',
|
||||
|
@ -106,16 +106,17 @@ Tag = namedtuple(
|
|||
|
||||
# FIXME: Some tag have only a few allowed values, we should ensure that
|
||||
known_tags: List[Tag] = [
|
||||
Tag('256', [TIFFType.UnsignedShort, TIFFType.UnsignedLong], [1], None, "ImageWidth"),
|
||||
Tag('257', [TIFFType.UnsignedShort, TIFFType.UnsignedLong], [1], None, "ImageHeight"),
|
||||
Tag('258', [TIFFType.UnsignedShort], [], None, "BitsPerSample"),
|
||||
Tag('259', [TIFFType.UnsignedShort], [1], None, "Compression", Compression),
|
||||
Tag('262', [TIFFType.UnsignedShort], [1], None, "PhotometricInterpretation", PhotometricInterpretation),
|
||||
Tag('273', [TIFFType.UnsignedShort, TIFFType.UnsignedLong], [], None, "StripOffsets"),
|
||||
Tag('256', [TIFFType.UnsignedShort, TIFFType.UnsignedLong], [1], None, "ImageWidth", is_required=True),
|
||||
Tag('257', [TIFFType.UnsignedShort, TIFFType.UnsignedLong], [1], None, "ImageHeight", is_required=True),
|
||||
Tag('258', [TIFFType.UnsignedShort], [], None, "BitsPerSample", is_required=True),
|
||||
Tag('259', [TIFFType.UnsignedShort], [1], None, "Compression", Compression, is_required=True),
|
||||
Tag('262', [TIFFType.UnsignedShort], [1], None, "PhotometricInterpretation",
|
||||
PhotometricInterpretation, is_required=True),
|
||||
Tag('273', [TIFFType.UnsignedShort, TIFFType.UnsignedLong], [], None, "StripOffsets", is_required=True),
|
||||
Tag('274', [TIFFType.UnsignedShort], [1], Orientation.Default, "Orientation", Orientation),
|
||||
Tag('277', [TIFFType.UnsignedShort], [1], None, "SamplesPerPixel"),
|
||||
Tag('278', [TIFFType.UnsignedShort, TIFFType.UnsignedLong], [1], None, "RowsPerStrip"),
|
||||
Tag('279', [TIFFType.UnsignedShort, TIFFType.UnsignedLong], [], None, "StripByteCounts"),
|
||||
Tag('277', [TIFFType.UnsignedShort], [1], None, "SamplesPerPixel", is_required=True),
|
||||
Tag('278', [TIFFType.UnsignedShort, TIFFType.UnsignedLong], [1], None, "RowsPerStrip", is_required=True),
|
||||
Tag('279', [TIFFType.UnsignedShort, TIFFType.UnsignedLong], [], None, "StripByteCounts", is_required=True),
|
||||
Tag('282', [TIFFType.UnsignedRational], [], None, "XResolution"),
|
||||
Tag('283', [TIFFType.UnsignedRational], [], None, "YResolution"),
|
||||
Tag('284', [TIFFType.UnsignedShort], [], PlanarConfiguration.Chunky, "PlanarConfiguration", PlanarConfiguration),
|
||||
|
@ -133,6 +134,8 @@ HANDLE_TAG_SIGNATURE_TEMPLATE = ("ErrorOr<void> {namespace}handle_tag(Metadata&
|
|||
HANDLE_TAG_SIGNATURE = HANDLE_TAG_SIGNATURE_TEMPLATE.format(namespace="")
|
||||
HANDLE_TAG_SIGNATURE_TIFF_NAMESPACE = HANDLE_TAG_SIGNATURE_TEMPLATE.format(namespace="TIFF::")
|
||||
|
||||
ENSURE_BASELINE_TAG_PRESENCE = "ErrorOr<void> ensure_baseline_tags_presence(Metadata const& metadata)"
|
||||
|
||||
LICENSE = R"""/*
|
||||
* Copyright (c) 2023, Lucas Chollet <lucas.chollet@serenityos.org>
|
||||
*
|
||||
|
@ -352,6 +355,7 @@ using Value = Variant<ByteBuffer, String, u32, Rational<u32>, i32, Rational<i32>
|
|||
{export_enum_to_string_converter([tag.associated_enum for tag in known_tags if tag.associated_enum] + [TIFFType])}
|
||||
|
||||
{HANDLE_TAG_SIGNATURE};
|
||||
{ENSURE_BASELINE_TAG_PRESENCE};
|
||||
|
||||
}}
|
||||
|
||||
|
@ -434,6 +438,10 @@ def generate_tag_handler_file(tags: List[Tag]) -> str:
|
|||
name_for_enum_tag_value(static_cast<{tag.associated_enum.export_name()}>(v.get<u32>()))));"""
|
||||
for tag in tags if tag.associated_enum])
|
||||
|
||||
ensure_tag_presence = '\n'.join([fR""" if (!metadata.{pascal_case_to_snake_case(tag.name)}().has_value())
|
||||
return Error::from_string_literal("Unable to decode image, missing required tag {tag.name}.");
|
||||
""" for tag in filter(lambda tag: tag.is_required, known_tags)])
|
||||
|
||||
output = fR"""{LICENSE}
|
||||
|
||||
#include <AK/Debug.h>
|
||||
|
@ -467,6 +475,13 @@ static String value_formatter(u32 tag_id, Value const& v) {{
|
|||
return MUST(builder.to_string());
|
||||
}}
|
||||
|
||||
{ENSURE_BASELINE_TAG_PRESENCE}
|
||||
{{
|
||||
{ensure_tag_presence}
|
||||
return {{}};
|
||||
}}
|
||||
|
||||
|
||||
{HANDLE_TAG_SIGNATURE}
|
||||
{{
|
||||
switch (tag) {{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue