Bugfix for some tags failing encoding due to more than one supported type

This was a recently introduced, preexisting bug caused by adding support
for multiple types for certain tags. This suddenly became an issue when
we added all remaining additional types and at least one of these was in
our testing data.
dustin/add_skipped_tags_tracking
Dustin Oprea 2020-05-19 02:32:43 -04:00
parent 15666b6093
commit 71d0c799d3
2 changed files with 35 additions and 5 deletions

View File

@ -185,9 +185,10 @@ func (bt *BuilderTag) SetValue(byteOrder binary.ByteOrder, value interface{}) (e
// NewStandardBuilderTag constructs a `BuilderTag` instance. The type is looked // NewStandardBuilderTag constructs a `BuilderTag` instance. The type is looked
// up. `ii` is the type of IFD that owns this tag. // up. `ii` is the type of IFD that owns this tag.
func NewStandardBuilderTag(ifdPath string, it *IndexedTag, byteOrder binary.ByteOrder, value interface{}) *BuilderTag { func NewStandardBuilderTag(ifdPath string, it *IndexedTag, byteOrder binary.ByteOrder, value interface{}) *BuilderTag {
if len(it.SupportedTypes) != 1 { // If there is more than one supported type, we'll go with the larger to
log.Panicf("NewStandardBuilderTag() IndexedTag argument must have exactly one supported-type: %v", it.SupportedTypes) // encode with. It'll use the same amount of fixed-space, and we'll
} // eliminate unnecessary overflows/issues.
tagType := it.WidestSupportedType()
var rawBytes []byte var rawBytes []byte
if it.DoesSupportType(exifcommon.TypeUndefined) == true { if it.DoesSupportType(exifcommon.TypeUndefined) == true {
@ -211,7 +212,7 @@ func NewStandardBuilderTag(ifdPath string, it *IndexedTag, byteOrder binary.Byte
return NewBuilderTag( return NewBuilderTag(
ifdPath, ifdPath,
it.Id, it.Id,
it.SupportedTypes[0], tagType,
tagValue, tagValue,
byteOrder) byteOrder)
} }

View File

@ -111,6 +111,34 @@ func (it *IndexedTag) Is(ifdPath string, id uint16) bool {
return it.Id == id && it.IfdPath == ifdPath return it.Id == id && it.IfdPath == ifdPath
} }
func (it *IndexedTag) WidestSupportedType() exifcommon.TagTypePrimitive {
if len(it.SupportedTypes) == 0 {
log.Panicf("IndexedTag [%s] (%d) has no supported types.", it.IfdPath, it.Id)
} else if len(it.SupportedTypes) == 1 {
return it.SupportedTypes[0]
}
supportsLong := false
supportsShort := false
for _, supportedType := range it.SupportedTypes {
if supportedType == exifcommon.TypeLong {
supportsLong = true
} else if supportedType == exifcommon.TypeShort {
supportsShort = true
}
}
// If it supports both long and short ints. This is currently our common
// and only case. The moment more are added to our tags database, we'll have
// to add more checks here if we add more than just a LONG and just a SHORT.
if supportsLong == true && supportsShort == true {
return exifcommon.TypeLong
}
log.Panicf("WidestSupportedType() case is not handled for tag [%s] (0x%04x): %v", it.IfdPath, it.Id, it.SupportedTypes)
return 0
}
// DoesSupportType returns true if this tag can be found/decoded with this type. // DoesSupportType returns true if this tag can be found/decoded with this type.
func (it *IndexedTag) DoesSupportType(tagType exifcommon.TagTypePrimitive) bool { func (it *IndexedTag) DoesSupportType(tagType exifcommon.TagTypePrimitive) bool {
// This is always a very small collection. So, we keep it unsorted. // This is always a very small collection. So, we keep it unsorted.
@ -178,7 +206,8 @@ func (ti *TagIndex) Add(it *IndexedTag) (err error) {
return nil return nil
} }
// Get returns information about the non-IFD tag given a tag ID. // Get returns information about the non-IFD tag given a tag ID. `ifdPath` must
// not be fully-qualified.
func (ti *TagIndex) Get(ifdPath string, id uint16) (it *IndexedTag, err error) { func (ti *TagIndex) Get(ifdPath string, id uint16) (it *IndexedTag, err error) {
defer func() { defer func() {
if state := recover(); state != nil { if state := recover(); state != nil {