Skip to content

C.CString(tag) is never freed in vipsExifStringTag / vipsExifIntTag (C heap memory leak) #483

Description

@kkato

Description

vipsExifStringTag and vipsExifIntTag in vips.go allocate a C string with C.CString(tag) but never free it, so every call leaks it on the C heap.

bimg/vips.go

Lines 245 to 250 in a14e08d

func vipsExifStringTag(image *C.VipsImage, tag string) string {
return vipsExifShort(C.GoString(C.vips_exif_tag(image, C.CString(tag))))
}
func vipsExifIntTag(image *C.VipsImage, tag string) int {
return int(C.vips_exif_tag_to_int(image, C.CString(tag)))

Impact

Metadata() reads ~50 EXIF fields through these two helpers, and Size() / Image.Metadata() go through Metadata() as well. So anything that reads image metadata per request leaks ~50 small allocations per image. Over time the C heap keeps growing — RSS climbs while the Go heap stays flat — until the process becomes unresponsive.

Suggested fix

Free it, the same way the other C.CString call sites already do (vipsWindowSize, vipsWatermark, vipsTransformICC):

func vipsExifStringTag(image *C.VipsImage, tag string) string {
	cTag := C.CString(tag)
	defer C.free(unsafe.Pointer(cTag))
	return vipsExifShort(C.GoString(C.vips_exif_tag(image, cTag)))
}

func vipsExifIntTag(image *C.VipsImage, tag string) int {
	cTag := C.CString(tag)
	defer C.free(unsafe.Pointer(cTag))
	return int(C.vips_exif_tag_to_int(image, cTag))
}

Still present on master (a14e08d). Happy to send a PR.

Related

Possibly related: #440, #282.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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