[MM-69126] Fix custom emoji upload size and GIF frame limits (#36984) (#37088)

* [MM-69126] Fix custom emoji upload size and GIF frame limits

* Assert 413 status and error ID in oversized emoji test

* Raise max emoji GIF frames to 70

* Enforce emoji GIF frame limit on the direct-write path
Этот коммит содержится в:
Felipe Martin
2026-06-25 12:05:34 +02:00
коммит произвёл GitHub
родитель cbfcecb37c
Коммит 638007314e
4 изменённых файлов: 66 добавлений и 4 удалений

Просмотреть файл

@@ -26,6 +26,7 @@ import (
"github.com/mattermost/mattermost/server/public/shared/request"
"github.com/mattermost/mattermost/server/v8/channels/store"
"github.com/mattermost/mattermost/server/v8/channels/utils"
"github.com/mattermost/mattermost/server/v8/channels/utils/imgutils"
)
const (
@@ -34,6 +35,7 @@ const (
MaxEmojiHeight = 128
MaxEmojiOriginalWidth = 1028
MaxEmojiOriginalHeight = 1028
MaxEmojiGIFFrames = 70
)
func (a *App) CreateEmoji(c request.CTX, sessionUserId string, emoji *model.Emoji, multiPartImageData *multipart.Form) (*model.Emoji, *model.AppError) {
@@ -122,6 +124,24 @@ func (a *App) uploadEmojiImage(c request.CTX, id string, filename string, file i
return model.NewAppError("uploadEmojiImage", "api.emoji.upload.seek.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
}
// Enforce the frame limit on every animated GIF, regardless of whether it
// needs resizing, so the cap applies to the direct-write path too.
isGIF := model.NewInfo(filename).MimeType == "image/gif"
if isGIF {
frameCount, err := imgutils.CountGIFFrames(file)
if err != nil {
return model.NewAppError("uploadEmojiImage", "api.emoji.upload.image.app_error", nil, "", http.StatusBadRequest).Wrap(err)
}
if frameCount > MaxEmojiGIFFrames {
return model.NewAppError("uploadEmojiImage", "api.emoji.upload.too_many_frames.app_error", map[string]any{
"MaxFrames": MaxEmojiGIFFrames,
}, "", http.StatusBadRequest)
}
if _, err = file.Seek(0, io.SeekStart); err != nil {
return model.NewAppError("uploadEmojiImage", "api.emoji.upload.seek.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
}
}
if config.Width <= MaxEmojiWidth && config.Height <= MaxEmojiHeight {
// No need to resize the image
_, appErr := a.WriteFile(file, getEmojiImagePath(id))
@@ -131,8 +151,7 @@ func (a *App) uploadEmojiImage(c request.CTX, id string, filename string, file i
// Create a buffer for the resized image
buf := &bytes.Buffer{}
info := model.NewInfo(filename)
if info.MimeType == "image/gif" {
if isGIF {
g, err := gif.DecodeAll(file)
if err != nil {
return model.NewAppError("uploadEmojiImage", "api.emoji.upload.large_image.gif_decode_error", nil, "", http.StatusBadRequest).Wrap(err)