media: never project zero image/video dimensions (crashes Telegram Desktop on reactions)

This commit is contained in:
Astra 2026-09-08 16:29:37 +01:00
parent 233a2399e9
commit f26468ef6d
3 changed files with 122 additions and 4 deletions

View file

@ -304,6 +304,10 @@ func (s *Service) prepareStickerSetDocument(ctx context.Context, doc domain.Docu
func (s *Service) ensureStickerMaterialShape(ctx context.Context, doc domain.Document) (domain.Document, error) {
mimeType := canonicalStickerMaterialMime(doc.StickerSetMaterialMime())
// A stored documentAttributeImageSize with a zero dimension is worse than a
// missing one: clients divide by it and crash. Strip any such attribute here
// so the branches below re-derive a real 512x512 (or decoded) size.
doc.Attributes = dropZeroImageSizeAttributes(doc.Attributes)
hasImageSize := false
hasVideo := false
for _, attr := range doc.Attributes {
@ -311,7 +315,9 @@ func (s *Service) ensureStickerMaterialShape(ctx context.Context, doc domain.Doc
case domain.DocAttrImageSize:
hasImageSize = true
case domain.DocAttrVideo:
hasVideo = true
if attr.W > 0 && attr.H > 0 {
hasVideo = true
}
}
}
switch mimeType {
@ -444,6 +450,20 @@ func (s *Service) rewriteStickerMaterialBlob(ctx context.Context, docID int64, d
return nil
}
// dropZeroImageSizeAttributes removes documentAttributeImageSize entries whose
// width or height is not positive. Such an attribute reaches clients as
// documentAttributeImageSize#0 and is divided by while sizing the render.
func dropZeroImageSizeAttributes(attrs []domain.DocumentAttribute) []domain.DocumentAttribute {
out := attrs[:0:0]
for _, a := range attrs {
if a.Kind == domain.DocAttrImageSize && (a.W <= 0 || a.H <= 0) {
continue
}
out = append(out, a)
}
return out
}
func replaceStickerMaterialFilename(attrs []domain.DocumentAttribute, fallback string) []domain.DocumentAttribute {
out := append([]domain.DocumentAttribute(nil), attrs...)
for i := range out {