Răsfoiți Sursa

Fix crashes during processing of large animated WebPs

DarthSim 1 an în urmă
părinte
comite
756958d2ca
5 a modificat fișierele cu 27 adăugiri și 0 ștergeri
  1. 1 0
      CHANGELOG.md
  2. 6 0
      processing/processing.go
  3. 7 0
      vips/vips.c
  4. 11 0
      vips/vips.go
  5. 2 0
      vips/vips.h

+ 1 - 0
CHANGELOG.md

@@ -8,6 +8,7 @@
 - Fix parsing of HEIF files with large boxes.
 - Fix wrong colors when the source image has a linear colorspace.
 - Fix wrong colors or opacity when the source image is a TIFF with a float sample format.
+- Fix crashes during processing of large animated WebPs.
 - (pro) Fix generating thumbnails for WebM videos with transparency.
 
 ## [3.19.0] - 2023-08-21

+ 6 - 0
processing/processing.go

@@ -155,6 +155,12 @@ func transformAnimated(ctx context.Context, img *vips.Image, po *options.Process
 		}
 	}()
 
+	// Splitting and joining back large WebPs may cause segfault.
+	// Caching page region cures this
+	if err = img.LineCache(frameHeight); err != nil {
+		return err
+	}
+
 	for i := 0; i < framesCount; i++ {
 		frame := new(vips.Image)
 

+ 7 - 0
vips/vips.c

@@ -714,6 +714,13 @@ vips_apply_watermark(VipsImage *in, VipsImage *watermark, VipsImage **out, int l
   return res;
 }
 
+int
+vips_linecache_seq(VipsImage *in, VipsImage **out, int tile_height)
+{
+  return vips_linecache(in, out, "tile_height", tile_height, "access", VIPS_ACCESS_SEQUENTIAL,
+      NULL);
+}
+
 int
 vips_arrayjoin_go(VipsImage **in, VipsImage **out, int n) {
   return vips_arrayjoin(in, out, n, "across", 1, NULL);

+ 11 - 0
vips/vips.go

@@ -406,6 +406,17 @@ func (img *Image) Clear() {
 	}
 }
 
+func (img *Image) LineCache(lines int) error {
+	var tmp *C.VipsImage
+
+	if C.vips_linecache_seq(img.VipsImage, &tmp, C.int(lines)) != 0 {
+		return Error()
+	}
+
+	C.swap_and_clear(&img.VipsImage, tmp)
+	return nil
+}
+
 func (img *Image) Arrayjoin(in []*Image) error {
 	var tmp *C.VipsImage
 

+ 2 - 0
vips/vips.h

@@ -76,6 +76,8 @@ int vips_embed_go(VipsImage *in, VipsImage **out, int x, int y, int width, int h
 int vips_apply_watermark(VipsImage *in, VipsImage *watermark, VipsImage **out, int left, int top,
     double opacity);
 
+int vips_linecache_seq(VipsImage *in, VipsImage **out, int tile_height);
+
 int vips_arrayjoin_go(VipsImage **in, VipsImage **out, int n);
 
 int vips_strip(VipsImage *in, VipsImage **out, int keep_exif_copyright);