imagick
imagick copied to clipboard
MagickCoreSignature assertion while CoalesceImages
Hi,
I've got panic by SIGABRT while making ThumbnailImage() with CoalesceImages() and gif-files.
magick/profile.c:120: CloneImageProfiles: Assertion `clone_image->signature == MagickCoreSignature' failed.
SIGABRT: abort
It seems that image blob was corrupted.
My environment:
OS: fedora 28
Go: go version go1.10.3 linux/amd64
ImageMagick: ImageMagick-6.9.9.38-1.fc28.x86_64
Panic stacktrace:
test: magick/profile.c:120: CloneImageProfiles: Assertion `clone_image->signature == MagickCoreSignature' failed.
SIGABRT: abort
PC=0x7ffa02ed2eab m=33 sigcode=18446744073709551610
goroutine 0 [idle]:
runtime: unknown pc 0x7ffa02ed2eab
stack: frame={sp:0x7ff9a0bf29f0, fp:0x0} stack=[0x7ff9a03f31d0,0x7ff9a0bf2dd0)
00007ff9a0bf28f0: 000000000000000c 00007ff964000920
00007ff9a0bf2900: 00000000000000b0 00000000000000c0
00007ff9a0bf2910: 0000000007fffff7 40e0000000000000
00007ff9a0bf2920: 4059000000000000 4059000000000000
00007ff9a0bf2930: 0000000000000000 0000000000000000
00007ff9a0bf2940: 0000000000000000 00007ffa009859b2
00007ff9a0bf2950: 0000000d00000001 00007ff900000001
00007ff9a0bf2960: 0000000000000000 0000000000000008
00007ff9a0bf2970: 40b1110000000000 40a4140000000000
00007ff9a0bf2980: 40a8180000000000 0000000000000000
00007ff9a0bf2990: 0000000000000000 0000000000000003
00007ff9a0bf29a0: 0000000d00000001 00007ff900000001
00007ff9a0bf29b0: 0000000000000000 0000000000000008
00007ff9a0bf29c0: 3032310000000000 705138f2a6326200
00007ff9a0bf29d0: 00007ff9a0bf2a10 0000000000000072
00007ff9a0bf29e0: 0000000000000072 00007ff9a0bf2c50
00007ff9a0bf29f0: <0000000000000000 00007ff9652d5ec0
00007ff9a0bf2a00: 00007ff9a0bf2ce0 00007ffa02f147b7
00007ff9a0bf2a10: 00000000fbad8000 00007ff9652d5ec0
00007ff9a0bf2a20: 00007ff9652d5f25 00007ff9652d5ec0
00007ff9a0bf2a30: 00007ff9652d5ec0 00007ff9652d5f32
00007ff9a0bf2a40: 00007ff9652d5fec 00007ff9652d5ec0
00007ff9a0bf2a50: 00007ff9652d5fec 0000000000000000
00007ff9a0bf2a60: 0000000000000000 0000000000000000
00007ff9a0bf2a70: fffffffe7fffffff ffffffffffffffff
00007ff9a0bf2a80: ffffffffffffffff ffffffffffffffff
00007ff9a0bf2a90: ffffffffffffffff ffffffffffffffff
00007ff9a0bf2aa0: ffffffffffffffff ffffffffffffffff
00007ff9a0bf2ab0: ffffffffffffffff ffffffffffffffff
00007ff9a0bf2ac0: ffffffffffffffff ffffffffffffffff
00007ff9a0bf2ad0: ffffffffffffffff ffffffffffffffff
00007ff9a0bf2ae0: ffffffffffffffff ffffffffffffffff
runtime: unknown pc 0x7ffa02ed2eab
stack: frame={sp:0x7ff9a0bf29f0, fp:0x0} stack=[0x7ff9a03f31d0,0x7ff9a0bf2dd0)
00007ff9a0bf28f0: 000000000000000c 00007ff964000920
00007ff9a0bf2900: 00000000000000b0 00000000000000c0
00007ff9a0bf2910: 0000000007fffff7 40e0000000000000
00007ff9a0bf2920: 4059000000000000 4059000000000000
00007ff9a0bf2930: 0000000000000000 0000000000000000
00007ff9a0bf2940: 0000000000000000 00007ffa009859b2
00007ff9a0bf2950: 0000000d00000001 00007ff900000001
00007ff9a0bf2960: 0000000000000000 0000000000000008
00007ff9a0bf2970: 40b1110000000000 40a4140000000000
00007ff9a0bf2980: 40a8180000000000 0000000000000000
00007ff9a0bf2990: 0000000000000000 0000000000000003
00007ff9a0bf29a0: 0000000d00000001 00007ff900000001
00007ff9a0bf29b0: 0000000000000000 0000000000000008
00007ff9a0bf29c0: 3032310000000000 705138f2a6326200
00007ff9a0bf29d0: 00007ff9a0bf2a10 0000000000000072
00007ff9a0bf29e0: 0000000000000072 00007ff9a0bf2c50
00007ff9a0bf29f0: <0000000000000000 00007ff9652d5ec0
00007ff9a0bf2a00: 00007ff9a0bf2ce0 00007ffa02f147b7
00007ff9a0bf2a10: 00000000fbad8000 00007ff9652d5ec0
00007ff9a0bf2a20: 00007ff9652d5f25 00007ff9652d5ec0
00007ff9a0bf2a30: 00007ff9652d5ec0 00007ff9652d5f32
00007ff9a0bf2a40: 00007ff9652d5fec 00007ff9652d5ec0
00007ff9a0bf2a50: 00007ff9652d5fec 0000000000000000
00007ff9a0bf2a60: 0000000000000000 0000000000000000
00007ff9a0bf2a70: fffffffe7fffffff ffffffffffffffff
00007ff9a0bf2a80: ffffffffffffffff ffffffffffffffff
00007ff9a0bf2a90: ffffffffffffffff ffffffffffffffff
00007ff9a0bf2aa0: ffffffffffffffff ffffffffffffffff
00007ff9a0bf2ab0: ffffffffffffffff ffffffffffffffff
00007ff9a0bf2ac0: ffffffffffffffff ffffffffffffffff
00007ff9a0bf2ad0: ffffffffffffffff ffffffffffffffff
00007ff9a0bf2ae0: ffffffffffffffff ffffffffffffffff
goroutine 486 [syscall]:
runtime.cgocall(0x4acfd0, 0xc4203ebe88, 0x454faf)
/usr/lib/golang/src/runtime/cgocall.go:128 +0x64 fp=0xc4203ebe58 sp=0xc4203ebe20 pc=0x418734
gopkg.in/gographics/imagick.v2/imagick._Cfunc_MagickCoalesceImages(0x7ff9652e8d50, 0x0)
_cgo_gotypes.go:4037 +0x4a fp=0xc4203ebe88 sp=0xc4203ebe58 pc=0x4a63aa
gopkg.in/gographics/imagick.v2/imagick.(*MagickWand).CoalesceImages.func1(0x7ff9652e8d50, 0x3)
/root/fe/gopath/src/gopkg.in/gographics/imagick.v2/imagick/magick_wand_image.go:357 +0x56 fp=0xc4203ebec0 sp=0xc4203ebe88 pc=0x4a80e6
gopkg.in/gographics/imagick.v2/imagick.(*MagickWand).CoalesceImages(0xc4200a8180, 0x3)
/root/fe/gopath/src/gopkg.in/gographics/imagick.v2/imagick/magick_wand_image.go:357 +0x2e fp=0xc4203ebee0 sp=0xc4203ebec0 pc=0x4a76fe
main.(*ImageMagick).Resize(0x791fe0, 0xc42758a000, 0x1780ac, 0x1782ac, 0x1782ac, 0x0, 0x0, 0x0, 0x0)
/root/fe/gopath/src/test/main.go:112 +0x2d8 fp=0xc4203ebf40 sp=0xc4203ebee0 pc=0x4aab48
main.do.func1(0xc426b24190, 0x4fbe80, 0x791fe0, 0x4f0253, 0x44)
/root/fe/gopath/src/test/main.go:66 +0xfd fp=0xc4203ebfb8 sp=0xc4203ebf40 pc=0x4aadbd
runtime.goexit()
/usr/lib/golang/src/runtime/asm_amd64.s:2361 +0x1 fp=0xc4203ebfc0 sp=0xc4203ebfb8 pc=0x4669b1
created by main.do
/root/fe/gopath/src/test/main.go:58 +0xf3
Test tool for reproducing, it may be required to run tool up to 10 times to get panic. Gif is attached to issue.
package main
import (
"fmt"
"gopkg.in/gographics/imagick.v2/imagick"
"io/ioutil"
"runtime"
"strings"
"sync"
)
func main() {
do()
}
func do() {
p, err := NewImageMagick()
if err != nil {
fmt.Println(err)
return
}
files := []string{
"1411808383_1369456619-ae4fe668748eb6af81bdf35a2d9a13ad.gif",
"1411808383_1369456619-ae4fe668748eb6af81bdf35a2d9a13ad.gif",
"1411808383_1369456619-ae4fe668748eb6af81bdf35a2d9a13ad.gif",
"1411808383_1369456619-ae4fe668748eb6af81bdf35a2d9a13ad.gif",
"1411808383_1369456619-ae4fe668748eb6af81bdf35a2d9a13ad.gif",
}
for k := 0; k < 10; k++ {
wg := &sync.WaitGroup{}
for j := 0; j < 10; j++ {
for i := range files {
wg.Add(1)
go func(file string) {
defer wg.Done()
raw, err := ioutil.ReadFile(file)
if err != nil {
fmt.Println(err)
return
}
_, err = p.Resize(raw)
if err != nil {
fmt.Println(err)
return
}
//fmt.Printf("result: %+v\n", i)
}(files[i])
}
}
wg.Wait()
fmt.Println("ok")
}
}
type Processor interface {
Resize([]byte) ([]byte, error)
}
type ImageMagick struct {
}
func (i *ImageMagick) Resize(blob []byte) ([]byte, error) {
mw := imagick.NewMagickWand()
err := mw.ReadImageBlob(blob)
if err != nil {
return nil, err
}
err = mw.StripImage()
if err != nil {
return nil, err
}
originalFormat := mw.GetImageFormat()
err = mw.SetImageFormat("gif")
if err != nil {
return nil, err
}
err = mw.SetImageCompressionQuality(75)
if err != nil {
return nil, err
}
if strings.ToLower(originalFormat) == "gif" {
mw = mw.CoalesceImages()
}
factor := float64(mw.GetImageHeight()) / float64(mw.GetImageWidth())
previewHeight := RoundTo2(uint(factor * float64(140)))
err = mw.ThumbnailImage(140, previewHeight)
if err != nil {
return nil, err
}
return mw.GetImageBlob(), nil
}
func NewImageMagick() (Processor, error) {
imagick.Initialize()
i := &ImageMagick{}
runtime.SetFinalizer(i, func(_ *ImageMagick) {
imagick.Terminate()
})
return i, nil
}
func RoundTo2(in uint) uint {
if in%2 != 0 {
return in + 1
}
return in
}
Much appreciated for including all the necessary details as well as a great repro. I was able to reproduce this as well on ImageMagick 6.9.9-35 using go 1.11 on ubuntu 16. However, this does not crash when tested against the oldest v2 version we support, 6.9.0-2. This means its entirely related to some kind of ImageMagick bug and not the Go imagick bindings. Maybe you could try this against one of the most recent 6.9.x releases to see if it is fixed? Or you can try a slightly older 6.9.x
@justinfx I get crash with "gopkg.in/gographics/imagick.v1 and 6.7.8.9-15 (centos7). And with 6.8.9.9 (ubuntu xenial).
I tried to free memory manually with Destroy instead of finalizers. It decreased frequency of crashes a lot, but it still can happen.
Well like I said, it didn't crash with 6.9.0-2 so the variable seems to be the version of ImageMagick
@justinfx I was able to reproduce panic at 6.9.0-2. I ran docker container ubuntu xenial, downloaded sources from https://launchpad.net/imagemagick/main/6.9.0-2/+download/ImageMagick-6.9.0-2.tar.gz, built it and after 1000+ iterations (outer k loop from example). I think that with 6.9.0-2 it is less frequent, but still possible.
I can take another look at this when I have some time. But I wonder, can you reproduce this for other formats besides gif?