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:
parent
e23537441e
commit
bf9e54620f
@ -1,6 +1,8 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
### Fix
|
||||||
|
- Fix parsing of HEIF files with large boxes.
|
||||||
|
|
||||||
## [3.19.0] - 2023-08-21
|
## [3.19.0] - 2023-08-21
|
||||||
### Add
|
### Add
|
||||||
|
@ -6,11 +6,12 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"math"
|
||||||
|
|
||||||
"github.com/imgproxy/imgproxy/v3/imagetype"
|
"github.com/imgproxy/imgproxy/v3/imagetype"
|
||||||
)
|
)
|
||||||
|
|
||||||
const heifBoxHeaderSize = int64(8)
|
const heifBoxHeaderSize = uint64(8)
|
||||||
|
|
||||||
var heicBrand = []byte("heic")
|
var heicBrand = []byte("heic")
|
||||||
var avifBrand = []byte("avif")
|
var avifBrand = []byte("avif")
|
||||||
@ -29,7 +30,7 @@ func (d *heifData) IsFilled() bool {
|
|||||||
return d.Format != imagetype.Unknown && d.Width > 0 && d.Height > 0
|
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 {
|
if buf, ok := r.(*bytes.Buffer); ok {
|
||||||
b = buf.Next(int(n))
|
b = buf.Next(int(n))
|
||||||
if len(b) == 0 {
|
if len(b) == 0 {
|
||||||
@ -43,7 +44,7 @@ func heifReadN(r io.Reader, n int64) (b []byte, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func heifDiscardN(r io.Reader, n int64) error {
|
func heifDiscardN(r io.Reader, n uint64) error {
|
||||||
if buf, ok := r.(*bytes.Buffer); ok {
|
if buf, ok := r.(*bytes.Buffer); ok {
|
||||||
_ = buf.Next(int(n))
|
_ = buf.Next(int(n))
|
||||||
return nil
|
return nil
|
||||||
@ -54,11 +55,11 @@ func heifDiscardN(r io.Reader, n int64) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := io.CopyN(io.Discard, r, n)
|
_, err := io.CopyN(io.Discard, r, int64(n))
|
||||||
return err
|
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
|
var b []byte
|
||||||
|
|
||||||
b, err = heifReadN(r, heifBoxHeaderSize)
|
b, err = heifReadN(r, heifBoxHeaderSize)
|
||||||
@ -66,9 +67,28 @@ func heifReadBoxHeader(r io.Reader) (boxType string, boxDataSize int64, err erro
|
|||||||
return
|
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])
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,7 +106,7 @@ func heifAssignFormat(d *heifData, brand []byte) bool {
|
|||||||
return false
|
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 {
|
if boxDataSize < 8 {
|
||||||
return errors.New("Invalid ftyp data")
|
return errors.New("Invalid ftyp data")
|
||||||
}
|
}
|
||||||
@ -101,7 +121,7 @@ func heifReadFtyp(d *heifData, r io.Reader, boxDataSize int64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if boxDataSize >= 12 {
|
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]) {
|
if heifAssignFormat(d, data[i:i+4]) {
|
||||||
return nil
|
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")
|
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 {
|
if boxDataSize < 4 {
|
||||||
return errors.New("Invalid meta data")
|
return errors.New("Invalid meta data")
|
||||||
}
|
}
|
||||||
@ -130,7 +150,7 @@ func heifReadMeta(d *heifData, r io.Reader, boxDataSize int64) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func heifReadHldr(r io.Reader, boxDataSize int64) error {
|
func heifReadHldr(r io.Reader, boxDataSize uint64) error {
|
||||||
if boxDataSize < 12 {
|
if boxDataSize < 12 {
|
||||||
return errors.New("Invalid hdlr data")
|
return errors.New("Invalid hdlr data")
|
||||||
}
|
}
|
||||||
@ -147,7 +167,7 @@ func heifReadHldr(r io.Reader, boxDataSize int64) error {
|
|||||||
return nil
|
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 {
|
if boxDataSize < 12 {
|
||||||
return 0, 0, errors.New("Invalid ispe data")
|
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 {
|
func heifReadBoxes(d *heifData, r io.Reader) error {
|
||||||
for {
|
for {
|
||||||
boxType, boxDataSize, err := heifReadBoxHeader(r)
|
boxType, boxDataSize, err := heifReadBoxHeader(r)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if boxDataSize < 0 {
|
|
||||||
return errors.New("Invalid box data")
|
|
||||||
}
|
|
||||||
|
|
||||||
// log.Printf("Box type: %s; Box data size: %d", boxType, boxDataSize)
|
|
||||||
|
|
||||||
switch boxType {
|
switch boxType {
|
||||||
case "ftyp":
|
case "ftyp":
|
||||||
if err := heifReadFtyp(d, r, boxDataSize); err != nil {
|
if err := heifReadFtyp(d, r, boxDataSize); err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user