1 // Copyright 2024 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 use crate::internal_utils::stream::*;
16 use crate::*;
17 
parse_exif_tiff_header_offset(stream: &mut IStream) -> AvifResult<u32>18 fn parse_exif_tiff_header_offset(stream: &mut IStream) -> AvifResult<u32> {
19     const TIFF_HEADER_BE: u32 = 0x4D4D002A; // MM0* (read as a big endian u32)
20     const TIFF_HEADER_LE: u32 = 0x49492A00; // II*0 (read as a big endian u32)
21     let mut expected_offset: u32 = 0;
22     let mut size = u32::try_from(stream.bytes_left()?).unwrap_or(u32::MAX);
23     while size > 0 {
24         let value = stream.read_u32().or(Err(AvifError::InvalidExifPayload))?;
25         if value == TIFF_HEADER_BE || value == TIFF_HEADER_LE {
26             stream.rewind(4)?;
27             return Ok(expected_offset);
28         }
29         checked_decr!(size, 4);
30         checked_incr!(expected_offset, 4);
31     }
32     // Could not find the TIFF header.
33     Err(AvifError::InvalidExifPayload)
34 }
35 
parse(stream: &mut IStream) -> AvifResult<()>36 pub fn parse(stream: &mut IStream) -> AvifResult<()> {
37     // unsigned int(32) exif_tiff_header_offset;
38     let offset = stream.read_u32().or(Err(AvifError::InvalidExifPayload))?;
39 
40     let expected_offset = parse_exif_tiff_header_offset(stream)?;
41     if offset != expected_offset {
42         return Err(AvifError::InvalidExifPayload);
43     }
44     Ok(())
45 }
46