diff --git a/Tests/oss-fuzz/fuzz_exif.py b/Tests/oss-fuzz/fuzz_exif.py new file mode 100644 index 000000000..7db804620 --- /dev/null +++ b/Tests/oss-fuzz/fuzz_exif.py @@ -0,0 +1,108 @@ +# Enhanced Fuzz Target for Pillow: EXIF Metadata Fuzzing + +This fuzz target focuses on testing the EXIF metadata handling capabilities of Pillow, which is an area not specifically targeted by the existing fuzzers. + +```python +#!/usr/bin/env python3 + +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import atheris +from atheris.import_hook import instrument_imports + +with instrument_imports(): + import io + import sys + from PIL import Image, ExifTags + +def TestOneInput(data): + if len(data) < 10: # Skip inputs that are too small + return + + try: + # Create a BytesIO object from the fuzzer data + image_io = io.BytesIO(data) + + # Try to open the image + with Image.open(image_io) as img: + # Test EXIF extraction + try: + exif = img._getexif() + if exif: + # Process EXIF data + for tag_id, value in exif.items(): + # Try to get the tag name + tag_name = ExifTags.TAGS.get(tag_id, tag_id) + + # Try to convert GPS info + if tag_id == 34853: # GPSInfo tag + for gps_tag, gps_value in value.items(): + gps_tag_name = ExifTags.GPSTAGS.get(gps_tag, gps_tag) + except Exception: + # Catch exceptions from EXIF processing + pass + + # Test thumbnail extraction from EXIF + try: + if hasattr(img, 'getexif'): + exif = img.getexif() + if exif: + # Try to extract thumbnail if present + if hasattr(exif, 'get_thumbnail'): + thumbnail = exif.get_thumbnail() + if thumbnail: + # Try to open the thumbnail + thumb_img = Image.open(io.BytesIO(thumbnail)) + thumb_img.load() + except Exception: + # Catch exceptions from thumbnail extraction + pass + + except Exception: + # Catch all other exceptions + pass + +def main(): + atheris.Setup(sys.argv, TestOneInput) + atheris.Fuzz() + +if __name__ == "__main__": + main() +``` + +## Features + +This fuzz target specifically tests: + +1. EXIF metadata extraction from images +2. Processing of EXIF tags and values +3. GPS information handling +4. Thumbnail extraction from EXIF data + +## Integration + +To integrate this fuzz target: + +1. Save it as `fuzz_exif.py` in the `Tests/oss-fuzz/` directory +2. Update the `build.sh` script to include this target in the build process +3. Test locally to ensure it works correctly +4. Submit as part of a pull request to the Pillow repository + +## Expected Benefits + +- Increased coverage of EXIF metadata handling code +- Potential discovery of bugs in metadata parsing +- Better handling of malformed EXIF data +- Improved security for applications processing images with metadata