1
0
mirror of https://github.com/imgproxy/imgproxy.git synced 2024-11-24 08:12:38 +02:00

Src file size check

This commit is contained in:
DarthSim 2019-01-21 16:36:31 +06:00
parent 6fa0c539bd
commit 0027db5f8a
3 changed files with 41 additions and 4 deletions

View File

@ -140,6 +140,7 @@ type config struct {
MaxSrcDimension int
MaxSrcResolution int
MaxSrcFileSize int
MaxGifFrames int
JpegProgressive bool
@ -253,6 +254,7 @@ func init() {
intEnvConfig(&conf.MaxSrcDimension, "IMGPROXY_MAX_SRC_DIMENSION")
megaIntEnvConfig(&conf.MaxSrcResolution, "IMGPROXY_MAX_SRC_RESOLUTION")
intEnvConfig(&conf.MaxSrcFileSize, "IMGPROXY_MAX_SRC_FILE_SIZE")
intEnvConfig(&conf.MaxGifFrames, "IMGPROXY_MAX_GIF_FRAMES")
boolEnvConfig(&conf.JpegProgressive, "IMGPROXY_JPEG_PROGRESSIVE")
@ -371,6 +373,10 @@ func init() {
logFatal("Max src resolution should be greater than 0, now - %d\n", conf.MaxSrcResolution)
}
if conf.MaxSrcFileSize < 0 {
logFatal("Max src file size should be greater than or equal to 0, now - %d\n", conf.MaxSrcFileSize)
}
if conf.MaxGifFrames <= 0 {
logFatal("Max GIF frames should be greater than 0, now - %d\n", conf.MaxGifFrames)
}

View File

@ -41,6 +41,7 @@ $ echo $(xxd -g 2 -l 64 -p /dev/random | tr -d '\n')
imgproxy protects you from so-called image bombs. Here is how you can specify 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`;
* `IMGPROXY_MAX_SRC_FILE_SIZE`: the maximum size of the source image, in bytes. Images with larger file size will be rejected. When `0`, file size check is disabled. Default: `0`;
imgproxy can process animated GIFs, but since this operation is pretty heavy, only one frame is processed by default. You can increase the maximum of GIF frames to process with the following variable:

View File

@ -25,7 +25,8 @@ var (
imageDataCtxKey = ctxKey("imageData")
errSourceDimensionsTooBig = newError(422, "Source image dimensions are too big", "Invalid source image")
errSourceResolutionTooBig = newError(422, "Source image resolution are too big", "Invalid source image")
errSourceResolutionTooBig = newError(422, "Source image resolution is too big", "Invalid source image")
errSourceFileTooBig = newError(422, "Source image file is too big", "Invalid source image")
errSourceImageTypeNotSupported = newError(422, "Source image type not supported", "Invalid source image")
)
@ -33,6 +34,26 @@ const msgSourceImageIsUnreachable = "Source image is unreachable"
var downloadBufPool *bufPool
type limitReader struct {
r io.ReadCloser
left int
}
func (lr *limitReader) Read(p []byte) (n int, err error) {
n, err = lr.r.Read(p)
lr.left = lr.left - n
if err == nil && lr.left < 0 {
err = errSourceFileTooBig
}
return
}
func (lr *limitReader) Close() error {
return lr.r.Close()
}
func initDownloading() {
transport := &http.Transport{
Proxy: http.ProxyFromEnvironment,
@ -76,9 +97,12 @@ func checkDimensions(width, height int) error {
func checkTypeAndDimensions(r io.Reader) (imageType, error) {
imgconf, imgtypeStr, err := image.DecodeConfig(r)
if err != nil {
if err == image.ErrFormat {
return imageTypeUnknown, errSourceImageTypeNotSupported
}
if err != nil {
return imageTypeUnknown, err
}
imgtype, imgtypeOk := imageTypes[imgtypeStr]
if !imgtypeOk || !vipsTypeSupportLoad[imgtype] {
@ -98,7 +122,13 @@ func readAndCheckImage(ctx context.Context, res *http.Response) (context.Context
downloadBufPool.put(buf)
}
imgtype, err := checkTypeAndDimensions(io.TeeReader(res.Body, buf))
body := res.Body
if conf.MaxSrcFileSize > 0 {
body = &limitReader{r: body, left: conf.MaxSrcFileSize}
}
imgtype, err := checkTypeAndDimensions(io.TeeReader(body, buf))
if err != nil {
return ctx, cancel, err
}
@ -116,7 +146,7 @@ func readAndCheckImage(ctx context.Context, res *http.Response) (context.Context
buf.Grow(contentLength - buf.Len())
}
if _, err = buf.ReadFrom(res.Body); err != nil {
if _, err = buf.ReadFrom(body); err != nil {
return ctx, cancel, newError(404, err.Error(), msgSourceImageIsUnreachable)
}