Skip to content

Re-reading data written from a list with A301 scene info causes crashes/ #75

Description

@henrisson

I'm using the code at the bottom to remove GPS-related information from images, and I feed it images from iPhones converted to jpg.

The images that are generated as a result display fine, are accepted by exiftool as well as pretty much every tool I've found, but if you feed them again to the same function, if panics with "EOF", trying to read a long integer. Example below.

I've tracked it down to an issue in encodeTagToBytes when the tagID is 0xa301: because type is unknown, it defaults to bytes, which in turn makes unitCount be 4 instead of 1. When the decoder re-reads the produced image, it now thinks it's an offset, not a value.

I've tried changing the yaml in tags_data.go to

- id: 0xa301
  name: SceneType
  type_name: BYTE

but this now prevents the 0xa301 tag from being written.

The following hack works however, in encodeTagToBytes()

if bt.tagId == 0xa301 {
	effectiveType = exifcommon.TypeLong
} 

I'm not sure what an more elegant way to do this would be.

Here's an example function that illustrate the issue if called twice, once with an iPhone image (converted to jpeg) and once with the result of the previous iteration.

func removeGPSFromImage(data io.ReadSeeker, size int) ([]byte, error) {
	mp := jpegstructure.NewJpegMediaParser()
	intfc, err := mp.Parse(data, size)
	if err != nil {
		return nil, fmt.Errorf("parsing image: %v", err)
	}

	sl, ok := intfc.(*jpegstructure.SegmentList)
	if !ok {
		return nil, fmt.Errorf("casting segment list: %v", err)
	}
	rootIb, err := sl.ConstructExifBuilder()
	if err != nil {
		return nil, fmt.Errorf("building the builder: %v", err)
	}

	n, err := rootIb.DeleteAll(exifcommon.IfdGpsInfoStandardIfdIdentity.TagId())
	if err != nil {
		return nil, fmt.Errorf("deleting GPS nodes: %v", err)
	}
	fmt.Printf("Removed %d GPS info\n", n)

	// Update the exif segment.
	err = sl.SetExif(rootIb)
	if err != nil {
		return nil, fmt.Errorf("setting new exif header: %v", err)
	}

	b := new(bytes.Buffer)
	err = sl.Write(b)

	if err != nil {
		return nil, fmt.Errorf("writing output buffer: %v", err)
	}
	return b.Bytes(), nil
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions