@@ -157,7 +157,7 @@ tiff_data_size(TIFFDataType tifftype)
157157 // Sizes of TIFFDataType members
158158 static size_t sizes[] = { 0 , 1 , 1 , 2 , 4 , 8 , 1 , 1 , 2 , 4 , 8 , 4 , 8 , 4 };
159159 const int num_data_sizes = sizeof (sizes) / sizeof (*sizes);
160- int dir_index = ( int ) tifftype;
160+ int dir_index = bitcast< int >( tifftype) ;
161161 if (dir_index < 0 || dir_index >= num_data_sizes) {
162162 // Inform caller about corrupted entry.
163163 return -1 ;
@@ -360,9 +360,8 @@ makernote_handler(const TagInfo& /*taginfo*/, const TIFFDirEntry& dir,
360360 if (spec.get_string_attribute (" Make" ) == " Canon" ) {
361361 std::vector<size_t > ifdoffsets { 0 };
362362 std::set<size_t > offsets_seen;
363- decode_ifd ((unsigned char *)buf.data () + dir.tdir_offset , buf, spec,
364- pvt::canon_maker_tagmap_ref (), offsets_seen, swapendian,
365- offset_adjustment);
363+ decode_ifd (buf, dir.tdir_offset , spec, pvt::canon_maker_tagmap_ref (),
364+ offsets_seen, swapendian, offset_adjustment);
366365 } else {
367366 // Maybe we just haven't parsed the Maker metadata yet?
368367 // Allow a second try later by just stashing the maker note offset.
@@ -668,8 +667,10 @@ add_exif_item_to_spec(ImageSpec& spec, const char* name,
668667 float * f = OIIO_ALLOCA (float , n);
669668 for (int i = 0 ; i < n; ++i) {
670669 unsigned int num, den;
671- num = ((const unsigned int *)dataptr)[2 * i + 0 ];
672- den = ((const unsigned int *)dataptr)[2 * i + 1 ]; // NOSONAR
670+ memcpy (&num, dataptr + (2 * i) * sizeof (unsigned int ),
671+ sizeof (unsigned int ));
672+ memcpy (&den, dataptr + (2 * i + 1 ) * sizeof (unsigned int ),
673+ sizeof (unsigned int )); // NOSONAR
673674 if (swab) {
674675 swap_endian (&num);
675676 swap_endian (&den);
@@ -687,8 +688,9 @@ add_exif_item_to_spec(ImageSpec& spec, const char* name,
687688 float * f = OIIO_ALLOCA (float , n);
688689 for (int i = 0 ; i < n; ++i) {
689690 int num, den;
690- num = ((const int *)dataptr)[2 * i + 0 ];
691- den = ((const int *)dataptr)[2 * i + 1 ]; // NOSONAR
691+ memcpy (&num, dataptr + (2 * i) * sizeof (int ), sizeof (int ));
692+ memcpy (&den, dataptr + (2 * i + 1 ) * sizeof (int ),
693+ sizeof (int )); // NOSONAR
692694 if (swab) {
693695 swap_endian (&num);
694696 swap_endian (&den);
@@ -767,7 +769,9 @@ read_exif_tag(ImageSpec& spec, const TIFFDirEntry* dirp, cspan<uint8_t> buf,
767769
768770 // Make a copy of the pointed-to TIFF directory, swab the components
769771 // if necessary.
770- TIFFDirEntry dir = *dirp;
772+ TIFFDirEntry dir;
773+ memcpy (&dir, dirp, sizeof (TIFFDirEntry));
774+ unsigned int unswapped_tdir_offset = dir.tdir_offset ;
771775 if (swab) {
772776 swap_endian (&dir.tdir_tag );
773777 swap_endian (&dir.tdir_type );
@@ -785,7 +789,7 @@ read_exif_tag(ImageSpec& spec, const TIFFDirEntry* dirp, cspan<uint8_t> buf,
785789 if (dir.tdir_tag == TIFFTAG_EXIFIFD || dir.tdir_tag == TIFFTAG_GPSIFD) {
786790 // Special case: It's a pointer to a private EXIF directory.
787791 // Handle the whole thing recursively.
788- unsigned int offset = dirp-> tdir_offset ; // int stored in offset itself
792+ auto offset = unswapped_tdir_offset ; // int stored in offset itself
789793 if (swab)
790794 swap_endian (&offset);
791795 if (offset >= size_t (buf.size ())) {
@@ -840,7 +844,7 @@ read_exif_tag(ImageSpec& spec, const TIFFDirEntry* dirp, cspan<uint8_t> buf,
840844 } else if (dir.tdir_tag == TIFFTAG_INTEROPERABILITYIFD) {
841845 // Special case: It's a pointer to a private EXIF directory.
842846 // Handle the whole thing recursively.
843- unsigned int offset = dirp-> tdir_offset ; // int stored in offset itself
847+ auto offset = unswapped_tdir_offset ; // int stored in offset itself
844848 if (swab)
845849 swap_endian (&offset);
846850 if (offset >= size_t (buf.size ())) {
@@ -1004,23 +1008,32 @@ encode_exif_entry(const ParamValue& p, int tag, std::vector<TIFFDirEntry>& dirs,
10041008
10051009
10061010
1007- // Decode a raw Exif data block and save all the metadata in an
1008- // ImageSpec. Return true if all is ok, false if the exif block was
1011+ // Decode a raw Exif data block and save all the metadata in an ImageSpec. The
1012+ // data is all inside buf. The ifd itself is at the position `ifd_offset`
1013+ // within the buf. Return true if all is ok, false if the exif block was
10091014// somehow malformed.
1010- void
1011- pvt::decode_ifd (const unsigned char * ifd, cspan<uint8_t > buf, ImageSpec& spec,
1015+ bool
1016+ pvt::decode_ifd (cspan<uint8_t > buf, size_t ifd_offset , ImageSpec& spec,
10121017 const TagMap& tag_map, std::set<size_t >& ifd_offsets_seen,
10131018 bool swab, int offset_adjustment)
10141019{
10151020 // Read the directory that the header pointed to. It should contain
10161021 // some number of directory entries containing tags to process.
1017- unsigned short ndirs = *(const unsigned short *)ifd;
1022+ if (ifd_offset + 2 > std::size (buf)) {
1023+ return false ; // asking us to read beyond the buffer
1024+ }
1025+ auto ifd = buf.data () + ifd_offset;
1026+ unsigned short ndirs = *(const unsigned short *)(buf.data () + ifd_offset);
10181027 if (swab)
10191028 swap_endian (&ndirs);
1029+ if (ifd_offset + 2 + ndirs * sizeof (TIFFDirEntry) > std::size (buf)) {
1030+ return false ; // asking us to read beyond the buffer
1031+ }
10201032 for (int d = 0 ; d < ndirs; ++d)
10211033 read_exif_tag (spec,
10221034 (const TIFFDirEntry*)(ifd + 2 + d * sizeof (TIFFDirEntry)),
10231035 buf, swab, offset_adjustment, ifd_offsets_seen, tag_map);
1036+ return true ;
10241037}
10251038
10261039
@@ -1140,12 +1153,12 @@ decode_exif(cspan<uint8_t> exif, ImageSpec& spec)
11401153 if (swab)
11411154 swap_endian (&head.tiff_diroff );
11421155
1143- const unsigned char * ifd = ((const unsigned char *)exif.data ()
1144- + head.tiff_diroff );
11451156 // keep track of IFD offsets we've already seen to avoid infinite
11461157 // recursion if there are circular references.
11471158 std::set<size_t > ifd_offsets_seen;
1148- decode_ifd (ifd, exif, spec, exif_tagmap_ref (), ifd_offsets_seen, swab);
1159+ if (!decode_ifd (exif, head.tiff_diroff , spec, exif_tagmap_ref (),
1160+ ifd_offsets_seen, swab))
1161+ return false ;
11491162
11501163 // A few tidbits to look for
11511164 ParamValue* p;
@@ -1172,9 +1185,10 @@ decode_exif(cspan<uint8_t> exif, ImageSpec& spec)
11721185 int makernote_offset = spec.get_int_attribute (" oiio:MakerNoteOffset" );
11731186 if (makernote_offset > 0 ) {
11741187 if (Strutil::iequals (spec.get_string_attribute (" Make" ), " Canon" )) {
1175- decode_ifd ((unsigned char *)exif.data () + makernote_offset, exif,
1176- spec, pvt::canon_maker_tagmap_ref (), ifd_offsets_seen,
1177- swab);
1188+ if (!decode_ifd (exif, makernote_offset, spec,
1189+ pvt::canon_maker_tagmap_ref (), ifd_offsets_seen,
1190+ swab))
1191+ return false ;
11781192 }
11791193 // Now we can erase the attrib we used to pass the message about
11801194 // the maker note offset.
0 commit comments