From c1543c029b1aa5733cf69ffd35b2c696dd7ddba6 Mon Sep 17 00:00:00 2001 From: tobi Date: Sun, 1 Sep 2024 17:35:31 +0200 Subject: [PATCH 1/6] [chore] Bump tooling versions, bump go -> v1.23.0 --- .drone.yml | 14 +-- Dockerfile | 4 +- internal/api/client/admin/emojicreate.go | 4 +- internal/api/client/admin/emojiupdate.go | 4 +- internal/api/model/attachment.go | 2 +- internal/cache/domain/domain.go | 2 +- internal/db/bundb/bundb.go | 17 ++-- internal/federation/dereferencing/emoji.go | 12 +-- internal/federation/dereferencing/media.go | 8 +- internal/httpclient/client.go | 4 +- internal/media/ffmpeg.go | 13 ++- internal/media/imaging.go | 110 +++++++++++++++++---- internal/media/refetch.go | 7 +- internal/processing/account/update.go | 16 +-- internal/processing/admin/emoji.go | 16 +-- internal/processing/media/create.go | 8 +- internal/typeutils/internaltofrontend.go | 14 +-- 17 files changed, 171 insertions(+), 84 deletions(-) diff --git a/.drone.yml b/.drone.yml index 1a5239a13..453a133f9 100644 --- a/.drone.yml +++ b/.drone.yml @@ -12,7 +12,7 @@ steps: # We use golangci-lint for linting. # See: https://golangci-lint.run/ - name: lint - image: golangci/golangci-lint:v1.57.2 + image: golangci/golangci-lint:v1.60.3 volumes: - name: go-build-cache path: /root/.cache/go-build @@ -28,7 +28,7 @@ steps: - pull_request - name: test - image: golang:1.22-alpine + image: golang:1.23.0-alpine volumes: - name: go-build-cache path: /root/.cache/go-build @@ -38,7 +38,7 @@ steps: path: /root/.cache/wazero environment: CGO_ENABLED: "0" - GTS_WAZERO_COMPILATION_CACHE: "/root/.cache/wazero" + GTS_WAZERO_COMPILATION_CACHE: "~/.cache/wazero" commands: - apk update --no-cache && apk add git - >- @@ -94,7 +94,7 @@ steps: - pull_request - name: snapshot - image: superseriousbusiness/gotosocial-drone-build:0.6.0 # https://github.com/superseriousbusiness/gotosocial-drone-build + image: superseriousbusiness/gotosocial-drone-build:0.7.0 # https://github.com/superseriousbusiness/gotosocial-drone-build volumes: - name: go-build-cache path: /root/.cache/go-build @@ -135,7 +135,7 @@ steps: - main - name: release - image: superseriousbusiness/gotosocial-drone-build:0.6.0 # https://github.com/superseriousbusiness/gotosocial-drone-build + image: superseriousbusiness/gotosocial-drone-build:0.7.0 # https://github.com/superseriousbusiness/gotosocial-drone-build volumes: - name: go-build-cache path: /root/.cache/go-build @@ -194,7 +194,7 @@ clone: steps: - name: mirror - image: superseriousbusiness/gotosocial-drone-build:0.6.0 + image: superseriousbusiness/gotosocial-drone-build:0.7.0 environment: ORIGIN_REPO: https://github.com/superseriousbusiness/gotosocial TARGET_REPO: https://codeberg.org/superseriousbusiness/gotosocial @@ -207,6 +207,6 @@ steps: --- kind: signature -hmac: f4008d87e4e5b67251eb89f255c1224e6ab5818828cab24fc319b8f829176058 +hmac: 90df190a8e49e082ec2a95738bdf44fb049a7ab64b71f522e1f1add1bb061a81 ... diff --git a/Dockerfile b/Dockerfile index 9ca0b2a28..c59fc1662 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ # Dockerfile reference: https://docs.docker.com/engine/reference/builder/ # stage 1: generate up-to-date swagger.yaml to put in the final container -FROM --platform=${BUILDPLATFORM} golang:1.22-alpine AS swagger +FROM --platform=${BUILDPLATFORM} golang:1.23.0-alpine AS swagger RUN \ ### Installs goswagger for building swagger definitions inside this container @@ -28,7 +28,7 @@ RUN yarn --cwd ./web/source install && \ rm -rf ./web/source # stage 3: build the executor container -FROM --platform=${TARGETPLATFORM} alpine:3.19.1 as executor +FROM --platform=${TARGETPLATFORM} alpine:3.20.2 as executor # switch to non-root user:group for GtS USER 1000:1000 diff --git a/internal/api/client/admin/emojicreate.go b/internal/api/client/admin/emojicreate.go index 75661f1c3..9696200de 100644 --- a/internal/api/client/admin/emojicreate.go +++ b/internal/api/client/admin/emojicreate.go @@ -145,8 +145,8 @@ func validateCreateEmoji(form *apimodel.EmojiCreateRequest) error { return errors.New("no emoji given") } - maxSize := config.GetMediaEmojiLocalMaxSize() - if form.Image.Size > int64(maxSize) { + maxSize := int64(config.GetMediaEmojiLocalMaxSize()) // #nosec G115 -- Already validated. + if form.Image.Size > maxSize { return fmt.Errorf("emoji image too large: image is %dKB but size limit for custom emojis is %dKB", form.Image.Size/1024, maxSize/1024) } diff --git a/internal/api/client/admin/emojiupdate.go b/internal/api/client/admin/emojiupdate.go index 37f67cabd..ec6987024 100644 --- a/internal/api/client/admin/emojiupdate.go +++ b/internal/api/client/admin/emojiupdate.go @@ -208,8 +208,8 @@ func validateUpdateEmoji(form *apimodel.EmojiUpdateRequest) error { } if hasImage { - maxSize := config.GetMediaEmojiLocalMaxSize() - if form.Image.Size > int64(maxSize) { + maxSize := int64(config.GetMediaEmojiLocalMaxSize()) // #nosec G115 -- Already validated. + if form.Image.Size > maxSize { return fmt.Errorf("emoji image too large: image is %dKB but size limit for custom emojis is %dKB", form.Image.Size/1024, maxSize/1024) } } diff --git a/internal/api/model/attachment.go b/internal/api/model/attachment.go index 21523a58e..f037a09aa 100644 --- a/internal/api/model/attachment.go +++ b/internal/api/model/attachment.go @@ -160,7 +160,7 @@ type MediaDimensions struct { Duration float32 `json:"duration,omitempty"` // Bitrate of the media in bits per second. // example: 1000000 - Bitrate int `json:"bitrate,omitempty"` + Bitrate uint64 `json:"bitrate,omitempty"` // Size of the media, in the format `[width]x[height]`. // Not set for audio. // example: 1920x1080 diff --git a/internal/cache/domain/domain.go b/internal/cache/domain/domain.go index 274a244f7..c9a43b1e5 100644 --- a/internal/cache/domain/domain.go +++ b/internal/cache/domain/domain.go @@ -220,7 +220,7 @@ func (n *node) getChild(part string) *node { for i < j { // avoid overflow when computing h - h := int(uint(i+j) >> 1) + h := int(uint(i+j) >> 1) // #nosec G115 // i ≤ h < j if n.child[h].part < part { diff --git a/internal/db/bundb/bundb.go b/internal/db/bundb/bundb.go index 0e58cb7fb..cf7e4a9c7 100644 --- a/internal/db/bundb/bundb.go +++ b/internal/db/bundb/bundb.go @@ -25,6 +25,7 @@ "encoding/pem" "errors" "fmt" + "math" "net/url" "os" "runtime" @@ -396,13 +397,12 @@ func maxOpenConns() int { // deriveBunDBPGOptions takes an application config and returns either a ready-to-use set of options // with sensible defaults, or an error if it's not satisfied by the provided config. func deriveBunDBPGOptions() (*pgx.ConnConfig, error) { - url := config.GetDbPostgresConnectionString() - - // if database URL is defined, ignore other DB related configuration fields - if url != "" { - cfg, err := pgx.ParseConfig(url) - return cfg, err + // If database URL is defined, ignore + // other DB-related configuration fields. + if url := config.GetDbPostgresConnectionString(); url != "" { + return pgx.ParseConfig(url) } + // these are all optional, the db adapter figures out defaults address := config.GetDbAddress() @@ -466,7 +466,10 @@ func deriveBunDBPGOptions() (*pgx.ConnConfig, error) { cfg.Host = address } if port := config.GetDbPort(); port > 0 { - cfg.Port = uint16(port) + if port > math.MaxUint16 { + return nil, errors.New("invalid port, must be in range 1-65535") + } + cfg.Port = uint16(port) // #nosec G115 -- Just validated above. } if u := config.GetDbUser(); u != "" { cfg.User = u diff --git a/internal/federation/dereferencing/emoji.go b/internal/federation/dereferencing/emoji.go index 3174fa2f9..f7fb01727 100644 --- a/internal/federation/dereferencing/emoji.go +++ b/internal/federation/dereferencing/emoji.go @@ -97,11 +97,11 @@ func() (*media.ProcessingEmoji, error) { } // Get maximum supported remote emoji size. - maxsz := config.GetMediaEmojiRemoteMaxSize() + maxsz := int64(config.GetMediaEmojiRemoteMaxSize()) // #nosec G115 -- Already validated. // Prepare data function to dereference remote emoji media. data := func(context.Context) (io.ReadCloser, error) { - return tsport.DereferenceMedia(ctx, url, int64(maxsz)) + return tsport.DereferenceMedia(ctx, url, maxsz) } // Create new emoji with prepared info. @@ -189,11 +189,11 @@ func() (*media.ProcessingEmoji, error) { } // Get maximum supported remote emoji size. - maxsz := config.GetMediaEmojiRemoteMaxSize() + maxsz := int64(config.GetMediaEmojiRemoteMaxSize()) // #nosec G115 -- Already validated. // Prepare data function to dereference remote emoji media. data := func(context.Context) (io.ReadCloser, error) { - return tsport.DereferenceMedia(ctx, url, int64(maxsz)) + return tsport.DereferenceMedia(ctx, url, maxsz) } // Update emoji with prepared info. @@ -255,11 +255,11 @@ func() (*media.ProcessingEmoji, error) { } // Get maximum supported remote emoji size. - maxsz := config.GetMediaEmojiRemoteMaxSize() + maxsz := int64(config.GetMediaEmojiRemoteMaxSize()) // #nosec G115 -- Already validated. // Prepare data function to dereference remote emoji media. data := func(context.Context) (io.ReadCloser, error) { - return tsport.DereferenceMedia(ctx, url, int64(maxsz)) + return tsport.DereferenceMedia(ctx, url, maxsz) } // Recache emoji with prepared info. diff --git a/internal/federation/dereferencing/media.go b/internal/federation/dereferencing/media.go index d4f583735..d4a2b46e1 100644 --- a/internal/federation/dereferencing/media.go +++ b/internal/federation/dereferencing/media.go @@ -77,14 +77,14 @@ func() (*media.ProcessingMedia, error) { } // Get maximum supported remote media size. - maxsz := config.GetMediaRemoteMaxSize() + maxsz := int64(config.GetMediaRemoteMaxSize()) // #nosec G115 -- Already validated. // Create media with prepared info. return d.mediaManager.CreateMedia( ctx, accountID, func(ctx context.Context) (io.ReadCloser, error) { - return tsport.DereferenceMedia(ctx, url, int64(maxsz)) + return tsport.DereferenceMedia(ctx, url, maxsz) }, info, ) @@ -168,14 +168,14 @@ func() (*media.ProcessingMedia, error) { } // Get maximum supported remote media size. - maxsz := config.GetMediaRemoteMaxSize() + maxsz := int64(config.GetMediaRemoteMaxSize()) // #nosec G115 -- Already validated. // Recache media with prepared info, // this will also update media in db. return d.mediaManager.CacheMedia( attach, func(ctx context.Context) (io.ReadCloser, error) { - return tsport.DereferenceMedia(ctx, url, int64(maxsz)) + return tsport.DereferenceMedia(ctx, url, maxsz) }, ), nil }, diff --git a/internal/httpclient/client.go b/internal/httpclient/client.go index 30ef0b04d..4f8494d5c 100644 --- a/internal/httpclient/client.go +++ b/internal/httpclient/client.go @@ -344,14 +344,14 @@ func (c *Client) do(r *Request) (rsp *http.Response, retry bool, err error) { if u, _ := strconv.ParseUint(after, 10, 32); u != 0 { // An integer no. of backoff seconds was provided. - r.backoff = time.Duration(u) * time.Second + r.backoff = time.Duration(u) * time.Second // #nosec G115 -- We clamp backoff below. } else if at, _ := http.ParseTime(after); !at.Before(now) { // An HTTP formatted future date-time was provided. r.backoff = at.Sub(now) } // Don't let their provided backoff exceed our max. - if max := baseBackoff * time.Duration(c.retries); // + if max := baseBackoff * time.Duration(c.retries); // #nosec G115 -- We control c.retries. r.backoff > max { r.backoff = max } diff --git a/internal/media/ffmpeg.go b/internal/media/ffmpeg.go index 58c2f9503..0e7e8b4b6 100644 --- a/internal/media/ffmpeg.go +++ b/internal/media/ffmpeg.go @@ -21,6 +21,7 @@ "context" "encoding/json" "errors" + "math" "os" "path" "strconv" @@ -544,10 +545,18 @@ func (res *ffprobeResult) Process() (*result, error) { if p := strings.SplitN(str, "/", 2); len(p) == 2 { n, _ := strconv.ParseUint(p[0], 10, 32) d, _ := strconv.ParseUint(p[1], 10, 32) - num, den = uint32(n), uint32(d) + + if n > math.MaxUint32 || d > math.MaxUint32 { + return nil, gtserror.Newf("overflowed numerator or denominator") + } + num, den = uint32(n), uint32(d) // #nosec G115 -- Just checked. } else { n, _ := strconv.ParseUint(p[0], 10, 32) - num = uint32(n) + + if n > math.MaxUint32 { + return nil, gtserror.Newf("overflowed numerator") + } + num = uint32(n) // #nosec G115 -- Just checked. } // Set final divised framerate. diff --git a/internal/media/imaging.go b/internal/media/imaging.go index a9f73a066..e724e22b8 100644 --- a/internal/media/imaging.go +++ b/internal/media/imaging.go @@ -399,9 +399,25 @@ func (s *scanner) scan(x1, y1, x2, y2 int, dst []uint8) { g16 := uint16(s[1]) b16 := uint16(s[2]) a16 := uint16(a) - d[0] = uint8(r16 * 0xff / a16) - d[1] = uint8(g16 * 0xff / a16) - d[2] = uint8(b16 * 0xff / a16) + + d0 := r16 * 0xff / a16 + if d0 > math.MaxUint8 { + panic("overflow d0") + } + + d1 := g16 * 0xff / a16 + if d1 > math.MaxUint8 { + panic("overflow d1") + } + + d2 := b16 * 0xff / a16 + if d2 > math.MaxUint8 { + panic("overflow d2") + } + + d[0] = uint8(d0) // #nosec G115 -- Just checked. + d[1] = uint8(d1) // #nosec G115 -- Just checked. + d[2] = uint8(d2) // #nosec G115 -- Just checked. d[3] = a } j += 4 @@ -431,9 +447,25 @@ func (s *scanner) scan(x1, y1, x2, y2 int, dst []uint8) { g32 := uint32(s[2])<<8 | uint32(s[3]) b32 := uint32(s[4])<<8 | uint32(s[5]) a32 := uint32(s[6])<<8 | uint32(s[7]) - d[0] = uint8((r32 * 0xffff / a32) >> 8) - d[1] = uint8((g32 * 0xffff / a32) >> 8) - d[2] = uint8((b32 * 0xffff / a32) >> 8) + + d0 := (r32 * 0xffff / a32) >> 8 + if d0 > math.MaxUint8 { + panic("overflow d0") + } + + d1 := (g32 * 0xffff / a32) >> 8 + if d1 > math.MaxUint8 { + panic("overflow d1") + } + + d2 := (b32 * 0xffff / a32) >> 8 + if d2 > math.MaxUint8 { + panic("overflow d2") + } + + d[0] = uint8(d0) // #nosec G115 -- Just checked. + d[1] = uint8(d1) // #nosec G115 -- Just checked. + d[2] = uint8(d2) // #nosec G115 -- Just checked. } d[3] = a j += 4 @@ -514,6 +546,9 @@ func (s *scanner) scan(x1, y1, x2, y2 int, dst []uint8) { } else { r = ^(r >> 31) } + if r > math.MaxUint8 { + panic("overflow r") + } g := yy1 - 22554*cb1 - 46802*cr1 if uint32(g)&0xff000000 == 0 { @@ -521,6 +556,9 @@ func (s *scanner) scan(x1, y1, x2, y2 int, dst []uint8) { } else { g = ^(g >> 31) } + if g > math.MaxUint8 { + panic("overflow g") + } b := yy1 + 116130*cb1 if uint32(b)&0xff000000 == 0 { @@ -528,11 +566,14 @@ func (s *scanner) scan(x1, y1, x2, y2 int, dst []uint8) { } else { b = ^(b >> 31) } + if b > math.MaxUint8 { + panic("overflow b") + } d := dst[j : j+4 : j+4] - d[0] = uint8(r) - d[1] = uint8(g) - d[2] = uint8(b) + d[0] = uint8(r) // #nosec G115 -- Just checked. + d[1] = uint8(g) // #nosec G115 -- Just checked. + d[2] = uint8(b) // #nosec G115 -- Just checked. d[3] = 0xff iy++ @@ -569,9 +610,24 @@ func (s *scanner) scan(x1, y1, x2, y2 int, dst []uint8) { d := dst[j : j+4 : j+4] switch a16 { case 0xffff: - d[0] = uint8(r16 >> 8) - d[1] = uint8(g16 >> 8) - d[2] = uint8(b16 >> 8) + d0 := r16 >> 8 + if d0 > math.MaxUint8 { + panic("overflow d0") + } + + d1 := g16 >> 8 + if d1 > math.MaxUint8 { + panic("overflow d1") + } + + d2 := b16 >> 8 + if d2 > math.MaxUint8 { + panic("overflow d2") + } + + d[0] = uint8(d0) // #nosec G115 -- Just checked. + d[1] = uint8(d1) // #nosec G115 -- Just checked. + d[2] = uint8(d2) // #nosec G115 -- Just checked. d[3] = 0xff case 0: d[0] = 0 @@ -579,10 +635,30 @@ func (s *scanner) scan(x1, y1, x2, y2 int, dst []uint8) { d[2] = 0 d[3] = 0 default: - d[0] = uint8(((r16 * 0xffff) / a16) >> 8) - d[1] = uint8(((g16 * 0xffff) / a16) >> 8) - d[2] = uint8(((b16 * 0xffff) / a16) >> 8) - d[3] = uint8(a16 >> 8) + d0 := ((r16 * 0xffff) / a16) >> 8 + if d0 > math.MaxUint8 { + panic("overflow d0") + } + + d1 := ((g16 * 0xffff) / a16) >> 8 + if d1 > math.MaxUint8 { + panic("overflow d1") + } + + d2 := ((b16 * 0xffff) / a16) >> 8 + if d2 > math.MaxUint8 { + panic("overflow d2") + } + + d3 := a16 >> 8 + if d3 > math.MaxUint8 { + panic("overflow d3") + } + + d[0] = uint8(d0) // #nosec G115 -- Just checked. + d[1] = uint8(d1) // #nosec G115 -- Just checked. + d[2] = uint8(d2) // #nosec G115 -- Just checked. + d[3] = uint8(d3) // #nosec G115 -- Just checked. } j += 4 } @@ -617,7 +693,7 @@ func clampFloat(x float64) uint8 { return 255 } if v > 0 { - return uint8(v) + return uint8(v) // #nosec G115 -- Just checked. } return 0 } diff --git a/internal/media/refetch.go b/internal/media/refetch.go index 5531f6d97..c467333c9 100644 --- a/internal/media/refetch.go +++ b/internal/media/refetch.go @@ -49,9 +49,6 @@ func (m *Manager) RefetchEmojis(ctx context.Context, domain string, dereferenceM refetchIDs []string ) - // Get max supported remote emoji media size. - maxsz := config.GetMediaEmojiRemoteMaxSize() - // page through emojis 20 at a time, looking for those with missing images for { // Fetch next block of emojis from database @@ -111,8 +108,10 @@ func (m *Manager) RefetchEmojis(ctx context.Context, domain string, dereferenceM continue } + // Get max supported remote emoji media size. + maxsz := int64(config.GetMediaEmojiRemoteMaxSize()) // #nosec G115 -- Already validated. dataFunc := func(ctx context.Context) (reader io.ReadCloser, err error) { - return dereferenceMedia(ctx, emojiImageIRI, int64(maxsz)) + return dereferenceMedia(ctx, emojiImageIRI, maxsz) } processingEmoji, err := m.UpdateEmoji(ctx, emoji, dataFunc, AdditionalEmojiInfo{ diff --git a/internal/processing/account/update.go b/internal/processing/account/update.go index fda871bd5..5666646df 100644 --- a/internal/processing/account/update.go +++ b/internal/processing/account/update.go @@ -366,11 +366,11 @@ func (p *Processor) UpdateAvatar( gtserror.WithCode, ) { // Get maximum supported local media size. - maxsz := config.GetMediaLocalMaxSize() + maxsz := int64(config.GetMediaLocalMaxSize()) // #nosec G115 -- Already validated. // Ensure media within size bounds. - if avatar.Size > int64(maxsz) { - text := fmt.Sprintf("media exceeds configured max size: %s", maxsz) + if avatar.Size > maxsz { + text := fmt.Sprintf("media exceeds configured max size: %d", maxsz) return nil, gtserror.NewErrorBadRequest(errors.New(text), text) } @@ -382,7 +382,7 @@ func (p *Processor) UpdateAvatar( } // Wrap the multipart file reader to ensure is limited to max. - rc, _, _ := iotools.UpdateReadCloserLimit(mpfile, int64(maxsz)) + rc, _, _ := iotools.UpdateReadCloserLimit(mpfile, maxsz) // Write to instance storage. return p.c.StoreLocalMedia(ctx, @@ -411,11 +411,11 @@ func (p *Processor) UpdateHeader( gtserror.WithCode, ) { // Get maximum supported local media size. - maxsz := config.GetMediaLocalMaxSize() + maxsz := int64(config.GetMediaLocalMaxSize()) // #nosec G115 -- Already validated. // Ensure media within size bounds. - if header.Size > int64(maxsz) { - text := fmt.Sprintf("media exceeds configured max size: %s", maxsz) + if header.Size > maxsz { + text := fmt.Sprintf("media exceeds configured max size: %d", maxsz) return nil, gtserror.NewErrorBadRequest(errors.New(text), text) } @@ -427,7 +427,7 @@ func (p *Processor) UpdateHeader( } // Wrap the multipart file reader to ensure is limited to max. - rc, _, _ := iotools.UpdateReadCloserLimit(mpfile, int64(maxsz)) + rc, _, _ := iotools.UpdateReadCloserLimit(mpfile, maxsz) // Write to instance storage. return p.c.StoreLocalMedia(ctx, diff --git a/internal/processing/admin/emoji.go b/internal/processing/admin/emoji.go index 70e196b95..95744c4e5 100644 --- a/internal/processing/admin/emoji.go +++ b/internal/processing/admin/emoji.go @@ -45,11 +45,11 @@ func (p *Processor) EmojiCreate( ) (*apimodel.Emoji, gtserror.WithCode) { // Get maximum supported local emoji size. - maxsz := config.GetMediaEmojiLocalMaxSize() + maxsz := int64(config.GetMediaEmojiLocalMaxSize()) // #nosec G115 -- Already validated. // Ensure media within size bounds. - if form.Image.Size > int64(maxsz) { - text := fmt.Sprintf("emoji exceeds configured max size: %s", maxsz) + if form.Image.Size > maxsz { + text := fmt.Sprintf("emoji exceeds configured max size: %d", maxsz) return nil, gtserror.NewErrorBadRequest(errors.New(text), text) } @@ -61,7 +61,7 @@ func (p *Processor) EmojiCreate( } // Wrap the multipart file reader to ensure is limited to max. - rc, _, _ := iotools.UpdateReadCloserLimit(mpfile, int64(maxsz)) + rc, _, _ := iotools.UpdateReadCloserLimit(mpfile, maxsz) data := func(context.Context) (io.ReadCloser, error) { return rc, nil } @@ -441,11 +441,11 @@ func (p *Processor) emojiUpdateModify( // We can do both at the same time :) // Get maximum supported local emoji size. - maxsz := config.GetMediaEmojiLocalMaxSize() + maxsz := int64(config.GetMediaEmojiLocalMaxSize()) // #nosec G115 -- Already validated. // Ensure media within size bounds. - if image.Size > int64(maxsz) { - text := fmt.Sprintf("emoji exceeds configured max size: %s", maxsz) + if image.Size > maxsz { + text := fmt.Sprintf("emoji exceeds configured max size: %d", maxsz) return nil, gtserror.NewErrorBadRequest(errors.New(text), text) } @@ -457,7 +457,7 @@ func (p *Processor) emojiUpdateModify( } // Wrap the multipart file reader to ensure is limited to max. - rc, _, _ := iotools.UpdateReadCloserLimit(mpfile, int64(maxsz)) + rc, _, _ := iotools.UpdateReadCloserLimit(mpfile, maxsz) data := func(context.Context) (io.ReadCloser, error) { return rc, nil } diff --git a/internal/processing/media/create.go b/internal/processing/media/create.go index b3a7d6052..64e44d999 100644 --- a/internal/processing/media/create.go +++ b/internal/processing/media/create.go @@ -35,11 +35,11 @@ func (p *Processor) Create(ctx context.Context, account *gtsmodel.Account, form *apimodel.AttachmentRequest) (*apimodel.Attachment, gtserror.WithCode) { // Get maximum supported local media size. - maxsz := config.GetMediaLocalMaxSize() + maxsz := int64(config.GetMediaLocalMaxSize()) // #nosec G115 -- Already validated. // Ensure media within size bounds. - if form.File.Size > int64(maxsz) { - text := fmt.Sprintf("media exceeds configured max size: %s", maxsz) + if form.File.Size > maxsz { + text := fmt.Sprintf("media exceeds configured max size: %d", maxsz) return nil, gtserror.NewErrorBadRequest(errors.New(text), text) } @@ -58,7 +58,7 @@ func (p *Processor) Create(ctx context.Context, account *gtsmodel.Account, form } // Wrap the multipart file reader to ensure is limited to max. - rc, _, _ := iotools.UpdateReadCloserLimit(mpfile, int64(maxsz)) + rc, _, _ := iotools.UpdateReadCloserLimit(mpfile, maxsz) // Create local media and write to instance storage. attachment, errWithCode := p.c.StoreLocalMedia(ctx, diff --git a/internal/typeutils/internaltofrontend.go b/internal/typeutils/internaltofrontend.go index 07a4c0836..276fb9fb2 100644 --- a/internal/typeutils/internaltofrontend.go +++ b/internal/typeutils/internaltofrontend.go @@ -645,7 +645,7 @@ func (c *Converter) AttachmentToAPIAttachment(ctx context.Context, media *gtsmod Size: toAPISize(media.FileMeta.Original.Width, media.FileMeta.Original.Height), FrameRate: toAPIFrameRate(media.FileMeta.Original.Framerate), Duration: util.PtrOrZero(media.FileMeta.Original.Duration), - Bitrate: int(util.PtrOrZero(media.FileMeta.Original.Bitrate)), + Bitrate: util.PtrOrZero(media.FileMeta.Original.Bitrate), } // Copy over local file URL. @@ -1511,9 +1511,9 @@ func (c *Converter) InstanceToAPIV1Instance(ctx context.Context, i *gtsmodel.Ins instance.Configuration.Statuses.CharactersReservedPerURL = instanceStatusesCharactersReservedPerURL instance.Configuration.Statuses.SupportedMimeTypes = instanceStatusesSupportedMimeTypes instance.Configuration.MediaAttachments.SupportedMimeTypes = media.SupportedMIMETypes - instance.Configuration.MediaAttachments.ImageSizeLimit = int(config.GetMediaRemoteMaxSize()) + instance.Configuration.MediaAttachments.ImageSizeLimit = int(config.GetMediaRemoteMaxSize()) // #nosec G115 -- Already validated. instance.Configuration.MediaAttachments.ImageMatrixLimit = instanceMediaAttachmentsImageMatrixLimit - instance.Configuration.MediaAttachments.VideoSizeLimit = int(config.GetMediaRemoteMaxSize()) + instance.Configuration.MediaAttachments.VideoSizeLimit = int(config.GetMediaRemoteMaxSize()) // #nosec G115 -- Already validated. instance.Configuration.MediaAttachments.VideoFrameRateLimit = instanceMediaAttachmentsVideoFrameRateLimit instance.Configuration.MediaAttachments.VideoMatrixLimit = instanceMediaAttachmentsVideoMatrixLimit instance.Configuration.Polls.MaxOptions = config.GetStatusesPollMaxOptions() @@ -1523,7 +1523,7 @@ func (c *Converter) InstanceToAPIV1Instance(ctx context.Context, i *gtsmodel.Ins instance.Configuration.Accounts.AllowCustomCSS = config.GetAccountsAllowCustomCSS() instance.Configuration.Accounts.MaxFeaturedTags = instanceAccountsMaxFeaturedTags instance.Configuration.Accounts.MaxProfileFields = instanceAccountsMaxProfileFields - instance.Configuration.Emojis.EmojiSizeLimit = int(config.GetMediaEmojiLocalMaxSize()) + instance.Configuration.Emojis.EmojiSizeLimit = int(config.GetMediaEmojiLocalMaxSize()) // #nosec G115 -- Already validated. instance.Configuration.OIDCEnabled = config.GetOIDCEnabled() // URLs @@ -1655,9 +1655,9 @@ func (c *Converter) InstanceToAPIV2Instance(ctx context.Context, i *gtsmodel.Ins instance.Configuration.Statuses.CharactersReservedPerURL = instanceStatusesCharactersReservedPerURL instance.Configuration.Statuses.SupportedMimeTypes = instanceStatusesSupportedMimeTypes instance.Configuration.MediaAttachments.SupportedMimeTypes = media.SupportedMIMETypes - instance.Configuration.MediaAttachments.ImageSizeLimit = int(config.GetMediaRemoteMaxSize()) + instance.Configuration.MediaAttachments.ImageSizeLimit = int(config.GetMediaRemoteMaxSize()) // #nosec G115 -- Already validated. instance.Configuration.MediaAttachments.ImageMatrixLimit = instanceMediaAttachmentsImageMatrixLimit - instance.Configuration.MediaAttachments.VideoSizeLimit = int(config.GetMediaRemoteMaxSize()) + instance.Configuration.MediaAttachments.VideoSizeLimit = int(config.GetMediaRemoteMaxSize()) // #nosec G115 -- Already validated. instance.Configuration.MediaAttachments.VideoFrameRateLimit = instanceMediaAttachmentsVideoFrameRateLimit instance.Configuration.MediaAttachments.VideoMatrixLimit = instanceMediaAttachmentsVideoMatrixLimit instance.Configuration.Polls.MaxOptions = config.GetStatusesPollMaxOptions() @@ -1667,7 +1667,7 @@ func (c *Converter) InstanceToAPIV2Instance(ctx context.Context, i *gtsmodel.Ins instance.Configuration.Accounts.AllowCustomCSS = config.GetAccountsAllowCustomCSS() instance.Configuration.Accounts.MaxFeaturedTags = instanceAccountsMaxFeaturedTags instance.Configuration.Accounts.MaxProfileFields = instanceAccountsMaxProfileFields - instance.Configuration.Emojis.EmojiSizeLimit = int(config.GetMediaEmojiLocalMaxSize()) + instance.Configuration.Emojis.EmojiSizeLimit = int(config.GetMediaEmojiLocalMaxSize()) // #nosec G115 -- Already validated. instance.Configuration.OIDCEnabled = config.GetOIDCEnabled() // registrations From bd4c4d79fe07b528b1f1e9824997d698f00cb751 Mon Sep 17 00:00:00 2001 From: tobi Date: Sun, 1 Sep 2024 17:37:17 +0200 Subject: [PATCH 2/6] undo silly change --- .drone.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index 453a133f9..ad2d19ac5 100644 --- a/.drone.yml +++ b/.drone.yml @@ -38,7 +38,7 @@ steps: path: /root/.cache/wazero environment: CGO_ENABLED: "0" - GTS_WAZERO_COMPILATION_CACHE: "~/.cache/wazero" + GTS_WAZERO_COMPILATION_CACHE: "/root/.cache/wazero" commands: - apk update --no-cache && apk add git - >- From 75d3fca08cdcbc90647043c72dda8f335cb7c372 Mon Sep 17 00:00:00 2001 From: tobi Date: Sun, 1 Sep 2024 17:42:45 +0200 Subject: [PATCH 3/6] sign --- .drone.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index ad2d19ac5..f3e5f11fc 100644 --- a/.drone.yml +++ b/.drone.yml @@ -207,6 +207,6 @@ steps: --- kind: signature -hmac: 90df190a8e49e082ec2a95738bdf44fb049a7ab64b71f522e1f1add1bb061a81 +hmac: 9810bf692fb1029c13b0a1e2f556e2306d16f7d3eec9ca6163a0499c147280c1 ... From 7c6c74243bdefeca2bfe9b6ebf8f027ee99f129c Mon Sep 17 00:00:00 2001 From: tobi Date: Sun, 1 Sep 2024 17:44:54 +0200 Subject: [PATCH 4/6] bump go version in go.mod --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index ab82ba8ae..b210fb1a2 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/superseriousbusiness/gotosocial -go 1.22.2 +go 1.23 replace modernc.org/sqlite => gitlab.com/NyaaaWhatsUpDoc/sqlite v1.29.9-concurrency-workaround From 8db3d6b700b1a8097a16ff27356d3dfed9c0f1e8 Mon Sep 17 00:00:00 2001 From: tobi Date: Mon, 2 Sep 2024 15:08:07 +0200 Subject: [PATCH 5/6] allow overflow in imaging --- internal/media/imaging.go | 108 ++++++-------------------------------- 1 file changed, 16 insertions(+), 92 deletions(-) diff --git a/internal/media/imaging.go b/internal/media/imaging.go index e724e22b8..23fd2f838 100644 --- a/internal/media/imaging.go +++ b/internal/media/imaging.go @@ -399,25 +399,9 @@ func (s *scanner) scan(x1, y1, x2, y2 int, dst []uint8) { g16 := uint16(s[1]) b16 := uint16(s[2]) a16 := uint16(a) - - d0 := r16 * 0xff / a16 - if d0 > math.MaxUint8 { - panic("overflow d0") - } - - d1 := g16 * 0xff / a16 - if d1 > math.MaxUint8 { - panic("overflow d1") - } - - d2 := b16 * 0xff / a16 - if d2 > math.MaxUint8 { - panic("overflow d2") - } - - d[0] = uint8(d0) // #nosec G115 -- Just checked. - d[1] = uint8(d1) // #nosec G115 -- Just checked. - d[2] = uint8(d2) // #nosec G115 -- Just checked. + d[0] = uint8(r16 * 0xff / a16) // #nosec G115 -- Overflow desired. + d[1] = uint8(g16 * 0xff / a16) // #nosec G115 -- Overflow desired. + d[2] = uint8(b16 * 0xff / a16) // #nosec G115 -- Overflow desired. d[3] = a } j += 4 @@ -447,25 +431,9 @@ func (s *scanner) scan(x1, y1, x2, y2 int, dst []uint8) { g32 := uint32(s[2])<<8 | uint32(s[3]) b32 := uint32(s[4])<<8 | uint32(s[5]) a32 := uint32(s[6])<<8 | uint32(s[7]) - - d0 := (r32 * 0xffff / a32) >> 8 - if d0 > math.MaxUint8 { - panic("overflow d0") - } - - d1 := (g32 * 0xffff / a32) >> 8 - if d1 > math.MaxUint8 { - panic("overflow d1") - } - - d2 := (b32 * 0xffff / a32) >> 8 - if d2 > math.MaxUint8 { - panic("overflow d2") - } - - d[0] = uint8(d0) // #nosec G115 -- Just checked. - d[1] = uint8(d1) // #nosec G115 -- Just checked. - d[2] = uint8(d2) // #nosec G115 -- Just checked. + d[0] = uint8((r32 * 0xffff / a32) >> 8) // #nosec G115 -- Overflow desired. + d[1] = uint8((g32 * 0xffff / a32) >> 8) // #nosec G115 -- Overflow desired. + d[2] = uint8((b32 * 0xffff / a32) >> 8) // #nosec G115 -- Overflow desired. } d[3] = a j += 4 @@ -546,9 +514,6 @@ func (s *scanner) scan(x1, y1, x2, y2 int, dst []uint8) { } else { r = ^(r >> 31) } - if r > math.MaxUint8 { - panic("overflow r") - } g := yy1 - 22554*cb1 - 46802*cr1 if uint32(g)&0xff000000 == 0 { @@ -556,9 +521,6 @@ func (s *scanner) scan(x1, y1, x2, y2 int, dst []uint8) { } else { g = ^(g >> 31) } - if g > math.MaxUint8 { - panic("overflow g") - } b := yy1 + 116130*cb1 if uint32(b)&0xff000000 == 0 { @@ -566,14 +528,11 @@ func (s *scanner) scan(x1, y1, x2, y2 int, dst []uint8) { } else { b = ^(b >> 31) } - if b > math.MaxUint8 { - panic("overflow b") - } d := dst[j : j+4 : j+4] - d[0] = uint8(r) // #nosec G115 -- Just checked. - d[1] = uint8(g) // #nosec G115 -- Just checked. - d[2] = uint8(b) // #nosec G115 -- Just checked. + d[0] = uint8(r) // #nosec G115 -- Overflow desired. + d[1] = uint8(g) // #nosec G115 -- Overflow desired. + d[2] = uint8(b) // #nosec G115 -- Overflow desired. d[3] = 0xff iy++ @@ -610,24 +569,9 @@ func (s *scanner) scan(x1, y1, x2, y2 int, dst []uint8) { d := dst[j : j+4 : j+4] switch a16 { case 0xffff: - d0 := r16 >> 8 - if d0 > math.MaxUint8 { - panic("overflow d0") - } - - d1 := g16 >> 8 - if d1 > math.MaxUint8 { - panic("overflow d1") - } - - d2 := b16 >> 8 - if d2 > math.MaxUint8 { - panic("overflow d2") - } - - d[0] = uint8(d0) // #nosec G115 -- Just checked. - d[1] = uint8(d1) // #nosec G115 -- Just checked. - d[2] = uint8(d2) // #nosec G115 -- Just checked. + d[0] = uint8(r16 >> 8) // #nosec G115 -- Overflow desired. + d[1] = uint8(g16 >> 8) // #nosec G115 -- Overflow desired. + d[2] = uint8(b16 >> 8) // #nosec G115 -- Overflow desired. d[3] = 0xff case 0: d[0] = 0 @@ -635,30 +579,10 @@ func (s *scanner) scan(x1, y1, x2, y2 int, dst []uint8) { d[2] = 0 d[3] = 0 default: - d0 := ((r16 * 0xffff) / a16) >> 8 - if d0 > math.MaxUint8 { - panic("overflow d0") - } - - d1 := ((g16 * 0xffff) / a16) >> 8 - if d1 > math.MaxUint8 { - panic("overflow d1") - } - - d2 := ((b16 * 0xffff) / a16) >> 8 - if d2 > math.MaxUint8 { - panic("overflow d2") - } - - d3 := a16 >> 8 - if d3 > math.MaxUint8 { - panic("overflow d3") - } - - d[0] = uint8(d0) // #nosec G115 -- Just checked. - d[1] = uint8(d1) // #nosec G115 -- Just checked. - d[2] = uint8(d2) // #nosec G115 -- Just checked. - d[3] = uint8(d3) // #nosec G115 -- Just checked. + d[0] = uint8(((r16 * 0xffff) / a16) >> 8) // #nosec G115 -- Overflow desired. + d[1] = uint8(((g16 * 0xffff) / a16) >> 8) // #nosec G115 -- Overflow desired. + d[2] = uint8(((b16 * 0xffff) / a16) >> 8) // #nosec G115 -- Overflow desired. + d[3] = uint8(a16 >> 8) // #nosec G115 -- Overflow desired. } j += 4 } From 4be1f780a10389493a8619c1320fb3149b086e01 Mon Sep 17 00:00:00 2001 From: tobi Date: Mon, 2 Sep 2024 15:14:27 +0200 Subject: [PATCH 6/6] goreleaser deprecation notices --- .goreleaser.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index 6a7fccfd0..6fec680dc 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -1,4 +1,5 @@ -# https://goreleaser.com +# Version 2 of GoReleaser: https://goreleaser.com/errors/version/ +version: 2 project_name: gotosocial before: # https://goreleaser.com/customization/hooks/ @@ -185,7 +186,7 @@ checksum: name_template: 'checksums.txt' snapshot: # https://goreleaser.com/customization/snapshots/ - name_template: "{{ incpatch .Version }}-SNAPSHOT" + version_template: "{{ incpatch .Version }}-SNAPSHOT" source: # https://goreleaser.com/customization/source/ enabled: true