فهرست منبع

Add IMGPROXY_MAX_ANIMATION_FRAME_RESOLUTION config

DarthSim 2 سال پیش
والد
کامیت
1ededbb11f
6فایلهای تغییر یافته به همراه30 افزوده شده و 12 حذف شده
  1. 3 0
      CHANGELOG.md
  2. 8 5
      config/config.go
  3. 4 2
      docs/configuration.md
  4. 1 1
      imagedata/read.go
  5. 1 1
      processing/processing.go
  6. 13 3
      security/image_size.go

+ 3 - 0
CHANGELOG.md

@@ -1,6 +1,9 @@
 # Changelog
 
 ## [Unreleased]
+### Add
+- Add `IMGPROXY_MAX_ANIMATION_FRAME_RESOLUTION` config.
+
 ### Change
 - Change `IMGPROXY_FORMAT_QUALITY` default value to `avif=65`.
 - Change `IMGPROXY_AVIF_SPEED` default value to `8`.

+ 8 - 5
config/config.go

@@ -35,11 +35,12 @@ var (
 
 	PathPrefix string
 
-	MaxSrcResolution   int
-	MaxSrcFileSize     int
-	MaxAnimationFrames int
-	MaxSvgCheckBytes   int
-	MaxRedirects       int
+	MaxSrcResolution            int
+	MaxSrcFileSize              int
+	MaxAnimationFrames          int
+	MaxAnimationFrameResolution int
+	MaxSvgCheckBytes            int
+	MaxRedirects                int
 
 	JpegProgressive       bool
 	PngInterlaced         bool
@@ -217,6 +218,7 @@ func Reset() {
 	MaxSrcResolution = 16800000
 	MaxSrcFileSize = 0
 	MaxAnimationFrames = 1
+	MaxAnimationFrameResolution = 0
 	MaxSvgCheckBytes = 32 * 1024
 	MaxRedirects = 10
 
@@ -386,6 +388,7 @@ func Configure() error {
 	configurators.Int(&MaxSvgCheckBytes, "IMGPROXY_MAX_SVG_CHECK_BYTES")
 
 	configurators.Int(&MaxAnimationFrames, "IMGPROXY_MAX_ANIMATION_FRAMES")
+	configurators.MegaInt(&MaxAnimationFrameResolution, "IMGPROXY_MAX_ANIMATION_FRAME_RESOLUTION")
 
 	configurators.Int(&MaxRedirects, "IMGPROXY_MAX_REDIRECTS")
 

+ 4 - 2
docs/configuration.md

@@ -60,13 +60,15 @@ echo $(xxd -g 2 -l 64 -p /dev/random | tr -d '\n')
 imgproxy protects you from so-called image bombs. Here's how you can specify the maximum image resolution which you consider reasonable:
 
 * `IMGPROXY_MAX_SRC_RESOLUTION`: the maximum resolution of the source image, in megapixels. Images with larger actual size will be rejected. Default: `16.8`
+
+**⚠️Warning:** When the source image is animated, imgproxy summarizes all its frames' resolutions while checking the source image resolution unless `IMGPROXY_MAX_ANIMATION_FRAME_RESOLUTION` is greater than zero.
+
 * `IMGPROXY_MAX_SRC_FILE_SIZE`: the maximum size of the source image, in bytes. Images with larger file size will be rejected. When set to `0`, file size check is disabled. Default: `0`
 
 imgproxy can process animated images (GIF, WebP), but since this operation is pretty memory heavy, only one frame is processed by default. You can increase the maximum animation frames that can be processed number of with the following variable:
 
 * `IMGPROXY_MAX_ANIMATION_FRAMES`: the maximum number of animated image frames that may be processed. Default: `1`
-
-**📝Note:** imgproxy summarizes all frame resolutions while checking the source image resolution.
+* `IMGPROXY_MAX_ANIMATION_FRAME_RESOLUTION`: the maximum resolution of the animated source image frame, in megapixels. Images with larger actual frame size will be rejected. When set to `0`, imgproxy will test the whole animated image resolution against `IMGPROXY_MAX_SRC_RESOLUTION` summarising all the frames' resolutions. Default: `0`
 
 To check if the source image is SVG, imgproxy reads some amount of bytes; by default it reads a maximum of 32KB. However, you can change this value using the following variable:
 

+ 1 - 1
imagedata/read.go

@@ -67,7 +67,7 @@ func readAndCheckImage(r io.Reader, contentLength int) (*ImageData, error) {
 		return nil, checkTimeoutErr(err)
 	}
 
-	if err = security.CheckDimensions(meta.Width(), meta.Height()); err != nil {
+	if err = security.CheckDimensions(meta.Width(), meta.Height(), 1); err != nil {
 		buf.Reset()
 		cancel()
 		return nil, err

+ 1 - 1
processing/processing.go

@@ -119,7 +119,7 @@ func transformAnimated(ctx context.Context, img *vips.Image, po *options.Process
 	framesCount := imath.Min(img.Height()/frameHeight, config.MaxAnimationFrames)
 
 	// Double check dimensions because animated image has many frames
-	if err = security.CheckDimensions(imgWidth, frameHeight*framesCount); err != nil {
+	if err = security.CheckDimensions(imgWidth, frameHeight, framesCount); err != nil {
 		return err
 	}
 

+ 13 - 3
security/image_size.go

@@ -3,13 +3,23 @@ package security
 import (
 	"github.com/imgproxy/imgproxy/v3/config"
 	"github.com/imgproxy/imgproxy/v3/ierrors"
+	"github.com/imgproxy/imgproxy/v3/imath"
 )
 
 var ErrSourceResolutionTooBig = ierrors.New(422, "Source image resolution is too big", "Invalid source image")
+var ErrSourceFrameResolutionTooBig = ierrors.New(422, "Source image frame resolution is too big", "Invalid source image")
 
-func CheckDimensions(width, height int) error {
-	if width*height > config.MaxSrcResolution {
-		return ErrSourceResolutionTooBig
+func CheckDimensions(width, height, frames int) error {
+	frames = imath.Max(frames, 1)
+
+	if frames > 1 && config.MaxAnimationFrameResolution > 0 {
+		if width*height > config.MaxAnimationFrameResolution {
+			return ErrSourceFrameResolutionTooBig
+		}
+	} else {
+		if width*height*frames > config.MaxSrcResolution {
+			return ErrSourceResolutionTooBig
+		}
 	}
 
 	return nil