private bool TryReadValue(out ExifValue exifValue) { exifValue = default; // 2 | 2 | 4 | 4 // tag | type | count | value offset if (this.RemainingLength < 12) { return(false); } var tag = (ExifTagValue)this.ReadUInt16(); ExifDataType dataType = EnumUtils.Parse(this.ReadUInt16(), ExifDataType.Unknown); // Ensure that the data type is valid if (dataType == ExifDataType.Unknown) { return(false); } uint numberOfComponents = this.ReadUInt32(); // Issue #132: ExifDataType == Undefined is treated like a byte array. // If numberOfComponents == 0 this value can only be handled as an inline value and must fallback to 4 (bytes) if (dataType == ExifDataType.Undefined && numberOfComponents == 0) { numberOfComponents = 4; } uint size = numberOfComponents * ExifDataTypes.GetSize(dataType); this.TryReadSpan(4, out ReadOnlySpan <byte> offsetBuffer); object value; if (size > 4) { int oldIndex = this.position; uint newIndex = this.ConvertToUInt32(offsetBuffer); // Ensure that the new index does not overrun the data if (newIndex > int.MaxValue) { this.AddInvalidTag(new UnkownExifTag(tag)); return(false); } this.position = (int)newIndex; if (this.RemainingLength < size) { this.AddInvalidTag(new UnkownExifTag(tag)); this.position = oldIndex; return(false); } this.TryReadSpan((int)size, out ReadOnlySpan <byte> dataBuffer); value = this.ConvertValue(dataType, dataBuffer, numberOfComponents); this.position = oldIndex; } else { value = this.ConvertValue(dataType, offsetBuffer, numberOfComponents); } exifValue = ExifValues.Create(tag) ?? ExifValues.Create(tag, dataType, numberOfComponents); if (exifValue is null) { this.AddInvalidTag(new UnkownExifTag(tag)); return(false); } if (!exifValue.TrySetValue(value)) { return(false); } return(true); }
private bool TryReadValue(out ExifValue exifValue) { // 2 | 2 | 4 | 4 // tag | type | count | value offset if (this.RemainingLength < 12) { exifValue = default; return(false); } ExifTag tag = this.ToEnum(this.ReadUInt16(), ExifTag.Unknown); uint type = this.ReadUInt16(); // Ensure that the data type is valid if (type == 0 || type > 12) { exifValue = new ExifValue(tag, ExifDataType.Unknown, null, false); return(true); } var dataType = (ExifDataType)type; object value; uint numberOfComponents = this.ReadUInt32(); // Issue #132: ExifDataType == Undefined is treated like a byte array. // If numberOfComponents == 0 this value can only be handled as an inline value and must fallback to 4 (bytes) if (dataType == ExifDataType.Undefined && numberOfComponents == 0) { numberOfComponents = 4; } uint size = numberOfComponents * ExifValue.GetSize(dataType); this.TryReadSpan(4, out ReadOnlySpan <byte> offsetBuffer); if (size > 4) { int oldIndex = this.position; uint newIndex = this.ConvertToUInt32(offsetBuffer); // Ensure that the new index does not overrun the data if (newIndex > int.MaxValue) { this.AddInvalidTag(tag); exifValue = default; return(false); } this.position = (int)newIndex; if (this.RemainingLength < size) { this.AddInvalidTag(tag); this.position = oldIndex; exifValue = default; return(false); } this.TryReadSpan((int)size, out ReadOnlySpan <byte> dataBuffer); value = this.ConvertValue(dataType, dataBuffer, numberOfComponents); this.position = oldIndex; } else { value = this.ConvertValue(dataType, offsetBuffer, numberOfComponents); } exifValue = new ExifValue(tag, dataType, value, isArray: value != null && numberOfComponents != 1); return(true); }