bool dng_info::ValidateIFD (dng_stream &stream, uint64 ifdOffset, int64 offsetDelta) { // Make sure we have a count. if (ifdOffset + 2 > stream.Length ()) { return false; } // Get entry count. stream.SetReadPosition (ifdOffset); uint32 ifdEntries = stream.Get_uint16 (); if (ifdEntries < 1) { return false; } // Make sure we have room for all entries and next IFD link. if (ifdOffset + 2 + ifdEntries * 12 + 4 > stream.Length ()) { return false; } // Check each entry. for (uint32 tag_index = 0; tag_index < ifdEntries; tag_index++) { stream.SetReadPosition (ifdOffset + 2 + tag_index * 12); stream.Skip (2); // Ignore tag code. uint32 tagType = stream.Get_uint16 (); uint32 tagCount = stream.Get_uint32 (); uint32 tag_type_size = TagTypeSize (tagType); if (tag_type_size == 0) { return false; } uint32 tag_data_size = tagCount * tag_type_size; if (tag_data_size > 4) { uint64 tagOffset = stream.Get_uint32 (); tagOffset += offsetDelta; if (tagOffset + tag_data_size > stream.Length ()) { return false; } } } return true; }
bool dng_camera_profile_info::ParseExtended (dng_stream &stream) { try { // Offsets are relative to the start of this structure, not the entire file. uint64 startPosition = stream.Position (); // Read header. Like a TIFF header, but with different magic number // Plus all offsets are relative to the start of the IFD, not to the // stream or file. uint16 byteOrder = stream.Get_uint16 (); if (byteOrder == byteOrderMM) fBigEndian = true; else if (byteOrder == byteOrderII) fBigEndian = false; else return false; TempBigEndian setEndianness (stream, fBigEndian); uint16 magicNumber = stream.Get_uint16 (); if (magicNumber != magicExtendedProfile) { return false; } uint32 offset = stream.Get_uint32 (); stream.Skip (offset - 8); // Start on IFD entries. uint32 ifdEntries = stream.Get_uint16 (); if (ifdEntries < 1) { return false; } for (uint32 tag_index = 0; tag_index < ifdEntries; tag_index++) { stream.SetReadPosition (startPosition + 8 + 2 + tag_index * 12); uint16 tagCode = stream.Get_uint16 (); uint32 tagType = stream.Get_uint16 (); uint32 tagCount = stream.Get_uint32 (); uint64 tagOffset = stream.Position (); if (TagTypeSize (tagType) * tagCount > 4) { tagOffset = startPosition + stream.Get_uint32 (); stream.SetReadPosition (tagOffset); } if (!ParseTag (stream, 0, tagCode, tagType, tagCount, tagOffset)) { #if qDNGValidate if (gVerbose) { stream.SetReadPosition (tagOffset); printf ("*"); DumpTagValues (stream, LookupTagType (tagType), 0, tagCode, tagType, tagCount); } #endif } } return true; } catch (...) { // Eat parsing errors. } return false; }