1
0
mirror of https://github.com/imgproxy/imgproxy.git synced 2025-01-08 10:45:04 +02:00

Fix parsing of HEIF files with large boxes

This commit is contained in:
DarthSim 2023-08-30 14:36:33 +04:00
parent e23537441e
commit bf9e54620f
2 changed files with 33 additions and 18 deletions

View File

@ -1,6 +1,8 @@
# Changelog
## [Unreleased]
### Fix
- Fix parsing of HEIF files with large boxes.
## [3.19.0] - 2023-08-21
### Add

View File

@ -6,11 +6,12 @@ import (
"errors"
"fmt"
"io"
"math"
"github.com/imgproxy/imgproxy/v3/imagetype"
)
const heifBoxHeaderSize = int64(8)
const heifBoxHeaderSize = uint64(8)
var heicBrand = []byte("heic")
var avifBrand = []byte("avif")
@ -29,7 +30,7 @@ func (d *heifData) IsFilled() bool {
return d.Format != imagetype.Unknown && d.Width > 0 && d.Height > 0
}
func heifReadN(r io.Reader, n int64) (b []byte, err error) {
func heifReadN(r io.Reader, n uint64) (b []byte, err error) {
if buf, ok := r.(*bytes.Buffer); ok {
b = buf.Next(int(n))
if len(b) == 0 {
@ -43,7 +44,7 @@ func heifReadN(r io.Reader, n int64) (b []byte, err error) {
return
}
func heifDiscardN(r io.Reader, n int64) error {
func heifDiscardN(r io.Reader, n uint64) error {
if buf, ok := r.(*bytes.Buffer); ok {
_ = buf.Next(int(n))
return nil
@ -54,11 +55,11 @@ func heifDiscardN(r io.Reader, n int64) error {
return err
}
_, err := io.CopyN(io.Discard, r, n)
_, err := io.CopyN(io.Discard, r, int64(n))
return err
}
func heifReadBoxHeader(r io.Reader) (boxType string, boxDataSize int64, err error) {
func heifReadBoxHeader(r io.Reader) (boxType string, boxDataSize uint64, err error) {
var b []byte
b, err = heifReadN(r, heifBoxHeaderSize)
@ -66,9 +67,28 @@ func heifReadBoxHeader(r io.Reader) (boxType string, boxDataSize int64, err erro
return
}
boxDataSize = int64(binary.BigEndian.Uint32(b[0:4])) - heifBoxHeaderSize
headerSize := heifBoxHeaderSize
boxDataSize = uint64(binary.BigEndian.Uint32(b[0:4]))
boxType = string(b[4:8])
if boxDataSize == 1 {
b, err = heifReadN(r, 8)
if err != nil {
return
}
boxDataSize = (uint64(binary.BigEndian.Uint32(b[0:4])) << 32) |
uint64(binary.BigEndian.Uint32(b[4:8]))
headerSize += 8
}
if boxDataSize < heifBoxHeaderSize || boxDataSize > math.MaxInt64 {
return "", 0, errors.New("Invalid box data size")
}
boxDataSize -= headerSize
return
}
@ -86,7 +106,7 @@ func heifAssignFormat(d *heifData, brand []byte) bool {
return false
}
func heifReadFtyp(d *heifData, r io.Reader, boxDataSize int64) error {
func heifReadFtyp(d *heifData, r io.Reader, boxDataSize uint64) error {
if boxDataSize < 8 {
return errors.New("Invalid ftyp data")
}
@ -101,7 +121,7 @@ func heifReadFtyp(d *heifData, r io.Reader, boxDataSize int64) error {
}
if boxDataSize >= 12 {
for i := int64(8); i < boxDataSize; i += 4 {
for i := uint64(8); i < boxDataSize; i += 4 {
if heifAssignFormat(d, data[i:i+4]) {
return nil
}
@ -111,7 +131,7 @@ func heifReadFtyp(d *heifData, r io.Reader, boxDataSize int64) error {
return errors.New("Image is not compatible with heic/avif")
}
func heifReadMeta(d *heifData, r io.Reader, boxDataSize int64) error {
func heifReadMeta(d *heifData, r io.Reader, boxDataSize uint64) error {
if boxDataSize < 4 {
return errors.New("Invalid meta data")
}
@ -130,7 +150,7 @@ func heifReadMeta(d *heifData, r io.Reader, boxDataSize int64) error {
return nil
}
func heifReadHldr(r io.Reader, boxDataSize int64) error {
func heifReadHldr(r io.Reader, boxDataSize uint64) error {
if boxDataSize < 12 {
return errors.New("Invalid hdlr data")
}
@ -147,7 +167,7 @@ func heifReadHldr(r io.Reader, boxDataSize int64) error {
return nil
}
func heifReadIspe(r io.Reader, boxDataSize int64) (w, h int64, err error) {
func heifReadIspe(r io.Reader, boxDataSize uint64) (w, h int64, err error) {
if boxDataSize < 12 {
return 0, 0, errors.New("Invalid ispe data")
}
@ -166,17 +186,10 @@ func heifReadIspe(r io.Reader, boxDataSize int64) (w, h int64, err error) {
func heifReadBoxes(d *heifData, r io.Reader) error {
for {
boxType, boxDataSize, err := heifReadBoxHeader(r)
if err != nil {
return err
}
if boxDataSize < 0 {
return errors.New("Invalid box data")
}
// log.Printf("Box type: %s; Box data size: %d", boxType, boxDataSize)
switch boxType {
case "ftyp":
if err := heifReadFtyp(d, r, boxDataSize); err != nil {