Prevent image decode panics, handle errors gracefully
Some checks failed
Run Integration Tests / test (push) Failing after 44s
Some checks failed
Run Integration Tests / test (push) Failing after 44s
This commit is contained in:
parent
fa266ec993
commit
40f322ef01
2 changed files with 34 additions and 47 deletions
|
@ -142,26 +142,12 @@ func cacheImage(imageURL, imageID string, imageType string) (string, bool, error
|
||||||
return cachedImagePath, true, nil
|
return cachedImagePath, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode the image based on the content type
|
// Decode image
|
||||||
var img image.Image
|
img, err := safeDecodeImage(contentType, data)
|
||||||
switch contentType {
|
if err != nil {
|
||||||
case "image/x-icon", "image/vnd.microsoft.icon":
|
printErr("Failed to decode favicon: %s [%s] (%v)", imageURL, imageID, err)
|
||||||
img, err = ico.Decode(bytes.NewReader(data))
|
|
||||||
case "image/jpeg":
|
|
||||||
img, err = jpeg.Decode(bytes.NewReader(data))
|
|
||||||
case "image/png":
|
|
||||||
img, err = png.Decode(bytes.NewReader(data))
|
|
||||||
case "image/gif":
|
|
||||||
img, err = gif.Decode(bytes.NewReader(data))
|
|
||||||
case "image/webp":
|
|
||||||
img, err = webp.Decode(bytes.NewReader(data))
|
|
||||||
case "image/bmp":
|
|
||||||
img, err = bmp.Decode(bytes.NewReader(data))
|
|
||||||
case "image/tiff":
|
|
||||||
img, err = tiff.Decode(bytes.NewReader(data))
|
|
||||||
default:
|
|
||||||
recordInvalidImageID(imageID)
|
recordInvalidImageID(imageID)
|
||||||
return "", false, fmt.Errorf("unsupported image type: %s", contentType)
|
return "", false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -522,6 +508,33 @@ func cleanupCache() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func safeDecodeImage(contentType string, data []byte) (img image.Image, err error) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
err = fmt.Errorf("image decode panic: %v", r)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
switch contentType {
|
||||||
|
case "image/x-icon", "image/vnd.microsoft.icon":
|
||||||
|
img, err = ico.Decode(bytes.NewReader(data))
|
||||||
|
case "image/jpeg":
|
||||||
|
img, err = jpeg.Decode(bytes.NewReader(data))
|
||||||
|
case "image/png":
|
||||||
|
img, err = png.Decode(bytes.NewReader(data))
|
||||||
|
case "image/gif":
|
||||||
|
img, err = gif.Decode(bytes.NewReader(data))
|
||||||
|
case "image/webp":
|
||||||
|
img, err = webp.Decode(bytes.NewReader(data))
|
||||||
|
case "image/bmp":
|
||||||
|
img, err = bmp.Decode(bytes.NewReader(data))
|
||||||
|
case "image/tiff":
|
||||||
|
img, err = tiff.Decode(bytes.NewReader(data))
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("unsupported image type: %s", contentType)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Serve missing.svg
|
// Serve missing.svg
|
||||||
func serveMissingImage(w http.ResponseWriter, r *http.Request) {
|
func serveMissingImage(w http.ResponseWriter, r *http.Request) {
|
||||||
missingImagePath := filepath.Join("static", "images", "missing.svg")
|
missingImagePath := filepath.Join("static", "images", "missing.svg")
|
||||||
|
|
30
favicon.go
30
favicon.go
|
@ -1,16 +1,12 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
"image/gif"
|
|
||||||
"image/jpeg"
|
|
||||||
"image/png"
|
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -21,10 +17,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/chai2010/webp"
|
"github.com/chai2010/webp"
|
||||||
"github.com/fyne-io/image/ico"
|
|
||||||
"golang.org/x/image/bmp"
|
|
||||||
"golang.org/x/image/draw"
|
"golang.org/x/image/draw"
|
||||||
"golang.org/x/image/tiff"
|
|
||||||
"golang.org/x/net/html"
|
"golang.org/x/net/html"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -504,28 +497,9 @@ func cacheFavicon(imageURL, imageID string) (string, bool, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode image
|
// Decode image
|
||||||
var img image.Image
|
img, err := safeDecodeImage(contentType, data)
|
||||||
var err error
|
|
||||||
switch contentType {
|
|
||||||
case "image/x-icon", "image/vnd.microsoft.icon":
|
|
||||||
img, err = ico.Decode(bytes.NewReader(data))
|
|
||||||
case "image/jpeg":
|
|
||||||
img, err = jpeg.Decode(bytes.NewReader(data))
|
|
||||||
case "image/png":
|
|
||||||
img, err = png.Decode(bytes.NewReader(data))
|
|
||||||
case "image/gif":
|
|
||||||
img, err = gif.Decode(bytes.NewReader(data))
|
|
||||||
case "image/webp":
|
|
||||||
img, err = webp.Decode(bytes.NewReader(data))
|
|
||||||
case "image/bmp":
|
|
||||||
img, err = bmp.Decode(bytes.NewReader(data))
|
|
||||||
case "image/tiff":
|
|
||||||
img, err = tiff.Decode(bytes.NewReader(data))
|
|
||||||
default:
|
|
||||||
recordInvalidImageID(imageID)
|
|
||||||
return "", false, fmt.Errorf("unsupported image type: %s", contentType)
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
printErr("Failed to decode favicon: %s [%s] (%v)", imageURL, imageID, err)
|
||||||
recordInvalidImageID(imageID)
|
recordInvalidImageID(imageID)
|
||||||
return "", false, err
|
return "", false, err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue