From c1543c029b1aa5733cf69ffd35b2c696dd7ddba6 Mon Sep 17 00:00:00 2001 From: tobi Date: Sun, 1 Sep 2024 17:35:31 +0200 Subject: [PATCH 01/15] [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 02/15] 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 03/15] 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 04/15] 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 05/15] 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 06/15] 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 From 275a3f8636abd5de62b5469a7003ba84cfbf2444 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sat, 12 Oct 2024 10:30:08 +0200 Subject: [PATCH 07/15] [chore] Upgrade golangci-lint, ignore existing int overflow warnings There is a new lint for unchecked int casts. Integer overflows are bad, but the old code that triggers this lint seems to be perfectly fine. Instead of disabling the lint entirely for new code as well, grandfather in existing code. --- .drone.yml | 2 +- internal/api/client/admin/emojicreate.go | 2 +- internal/api/client/admin/emojiupdate.go | 2 +- internal/cache/domain/domain.go | 2 +- internal/db/bundb/bundb.go | 2 +- internal/federation/dereferencing/emoji.go | 6 ++-- internal/federation/dereferencing/media.go | 4 +-- internal/httpclient/client.go | 4 +-- internal/media/imaging.go | 38 +++++++++++----------- internal/media/refetch.go | 2 +- internal/media/util.go | 2 +- internal/middleware/logger.go | 2 +- internal/middleware/requestid.go | 2 +- internal/middleware/throttling.go | 2 +- internal/processing/account/update.go | 8 ++--- internal/processing/admin/emoji.go | 10 +++--- internal/processing/media/create.go | 4 +-- internal/transport/derefmedia.go | 2 +- internal/typeutils/internaltofrontend.go | 20 ++++++------ 19 files changed, 58 insertions(+), 58 deletions(-) diff --git a/.drone.yml b/.drone.yml index 5ae306b69..88e9ce8f1 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.61.0 volumes: - name: go-build-cache path: /root/.cache/go-build diff --git a/internal/api/client/admin/emojicreate.go b/internal/api/client/admin/emojicreate.go index 75661f1c3..02c9466f8 100644 --- a/internal/api/client/admin/emojicreate.go +++ b/internal/api/client/admin/emojicreate.go @@ -146,7 +146,7 @@ func validateCreateEmoji(form *apimodel.EmojiCreateRequest) error { } maxSize := config.GetMediaEmojiLocalMaxSize() - if form.Image.Size > int64(maxSize) { + if form.Image.Size > int64(maxSize) { //nolint:gosec 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..3588bd83f 100644 --- a/internal/api/client/admin/emojiupdate.go +++ b/internal/api/client/admin/emojiupdate.go @@ -209,7 +209,7 @@ func validateUpdateEmoji(form *apimodel.EmojiUpdateRequest) error { if hasImage { maxSize := config.GetMediaEmojiLocalMaxSize() - if form.Image.Size > int64(maxSize) { + if form.Image.Size > int64(maxSize) { //nolint:gosec 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/cache/domain/domain.go b/internal/cache/domain/domain.go index 274a244f7..415a63ca7 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) //nolint:gosec // i ≤ h < j if n.child[h].part < part { diff --git a/internal/db/bundb/bundb.go b/internal/db/bundb/bundb.go index 45607ea15..ac062b25e 100644 --- a/internal/db/bundb/bundb.go +++ b/internal/db/bundb/bundb.go @@ -477,7 +477,7 @@ func deriveBunDBPGOptions() (*pgx.ConnConfig, error) { cfg.Host = address } if port := config.GetDbPort(); port > 0 { - cfg.Port = uint16(port) + cfg.Port = uint16(port) //nolint:gosec } if u := config.GetDbUser(); u != "" { cfg.User = u diff --git a/internal/federation/dereferencing/emoji.go b/internal/federation/dereferencing/emoji.go index 12c648556..5290f4ac8 100644 --- a/internal/federation/dereferencing/emoji.go +++ b/internal/federation/dereferencing/emoji.go @@ -101,7 +101,7 @@ func() (*media.ProcessingEmoji, error) { // 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, int64(maxsz)) //nolint:gosec } // Create new emoji with prepared info. @@ -193,7 +193,7 @@ func() (*media.ProcessingEmoji, error) { // 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, int64(maxsz)) //nolint:gosec } // Update emoji with prepared info. @@ -259,7 +259,7 @@ func() (*media.ProcessingEmoji, error) { // 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, int64(maxsz)) //nolint:gosec } // Recache emoji with prepared info. diff --git a/internal/federation/dereferencing/media.go b/internal/federation/dereferencing/media.go index 859e5603f..3c378b11b 100644 --- a/internal/federation/dereferencing/media.go +++ b/internal/federation/dereferencing/media.go @@ -84,7 +84,7 @@ func() (*media.ProcessingMedia, error) { ctx, accountID, func(ctx context.Context) (io.ReadCloser, error) { - return tsport.DereferenceMedia(ctx, url, int64(maxsz)) + return tsport.DereferenceMedia(ctx, url, int64(maxsz)) //nolint:gosec }, info, ) @@ -175,7 +175,7 @@ func() (*media.ProcessingMedia, error) { return d.mediaManager.CacheMedia( attach, func(ctx context.Context) (io.ReadCloser, error) { - return tsport.DereferenceMedia(ctx, url, int64(maxsz)) + return tsport.DereferenceMedia(ctx, url, int64(maxsz)) //nolint:gosec }, ), nil }, diff --git a/internal/httpclient/client.go b/internal/httpclient/client.go index 8a5f51c21..3496b081e 100644 --- a/internal/httpclient/client.go +++ b/internal/httpclient/client.go @@ -340,14 +340,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 //nolint:gosec } 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); //nolint:gosec r.backoff > max { r.backoff = max } diff --git a/internal/media/imaging.go b/internal/media/imaging.go index a9f73a066..ea1550ec9 100644 --- a/internal/media/imaging.go +++ b/internal/media/imaging.go @@ -399,9 +399,9 @@ 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) + d[0] = uint8(r16 * 0xff / a16) //nolint:gosec + d[1] = uint8(g16 * 0xff / a16) //nolint:gosec + d[2] = uint8(b16 * 0xff / a16) //nolint:gosec d[3] = a } j += 4 @@ -431,9 +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]) - d[0] = uint8((r32 * 0xffff / a32) >> 8) - d[1] = uint8((g32 * 0xffff / a32) >> 8) - d[2] = uint8((b32 * 0xffff / a32) >> 8) + d[0] = uint8((r32 * 0xffff / a32) >> 8) //nolint:gosec + d[1] = uint8((g32 * 0xffff / a32) >> 8) //nolint:gosec + d[2] = uint8((b32 * 0xffff / a32) >> 8) //nolint:gosec } d[3] = a j += 4 @@ -509,30 +509,30 @@ func (s *scanner) scan(x1, y1, x2, y2 int, dst []uint8) { cr1 := int32(img.Cr[ic]) - 128 r := yy1 + 91881*cr1 - if uint32(r)&0xff000000 == 0 { + if uint32(r)&0xff000000 == 0 { //nolint:gosec r >>= 16 } else { r = ^(r >> 31) } g := yy1 - 22554*cb1 - 46802*cr1 - if uint32(g)&0xff000000 == 0 { + if uint32(g)&0xff000000 == 0 { //nolint:gosec g >>= 16 } else { g = ^(g >> 31) } b := yy1 + 116130*cb1 - if uint32(b)&0xff000000 == 0 { + if uint32(b)&0xff000000 == 0 { //nolint:gosec b >>= 16 } else { b = ^(b >> 31) } d := dst[j : j+4 : j+4] - d[0] = uint8(r) - d[1] = uint8(g) - d[2] = uint8(b) + d[0] = uint8(r) //nolint:gosec + d[1] = uint8(g) //nolint:gosec + d[2] = uint8(b) //nolint:gosec d[3] = 0xff iy++ @@ -569,9 +569,9 @@ 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) + d[0] = uint8(r16 >> 8) //nolint:gosec + d[1] = uint8(g16 >> 8) //nolint:gosec + d[2] = uint8(b16 >> 8) //nolint:gosec d[3] = 0xff case 0: d[0] = 0 @@ -579,10 +579,10 @@ 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) + d[0] = uint8(((r16 * 0xffff) / a16) >> 8) //nolint:gosec + d[1] = uint8(((g16 * 0xffff) / a16) >> 8) //nolint:gosec + d[2] = uint8(((b16 * 0xffff) / a16) >> 8) //nolint:gosec + d[3] = uint8(a16 >> 8) //nolint:gosec } j += 4 } diff --git a/internal/media/refetch.go b/internal/media/refetch.go index 5531f6d97..b84573cc8 100644 --- a/internal/media/refetch.go +++ b/internal/media/refetch.go @@ -112,7 +112,7 @@ func (m *Manager) RefetchEmojis(ctx context.Context, domain string, dereferenceM } dataFunc := func(ctx context.Context) (reader io.ReadCloser, err error) { - return dereferenceMedia(ctx, emojiImageIRI, int64(maxsz)) + return dereferenceMedia(ctx, emojiImageIRI, int64(maxsz)) //nolint:gosec } processingEmoji, err := m.UpdateEmoji(ctx, emoji, dataFunc, AdditionalEmojiInfo{ diff --git a/internal/media/util.go b/internal/media/util.go index 538d6f572..f05573bd9 100644 --- a/internal/media/util.go +++ b/internal/media/util.go @@ -145,7 +145,7 @@ func drainToTmp(rc io.ReadCloser) (string, error) { // Check to see if limit was reached, // (produces more useful error messages). if lr != nil && lr.N <= 0 { - err := fmt.Errorf("reached read limit %s", bytesize.Size(limit)) + err := fmt.Errorf("reached read limit %s", bytesize.Size(limit)) //nolint:gosec return path, gtserror.SetLimitReached(err) } diff --git a/internal/middleware/logger.go b/internal/middleware/logger.go index 097c73cbd..b21b4d072 100644 --- a/internal/middleware/logger.go +++ b/internal/middleware/logger.go @@ -123,7 +123,7 @@ func Logger(logClientIP bool) gin.HandlerFunc { } // Generate a nicer looking bytecount - size := bytesize.Size(c.Writer.Size()) + size := bytesize.Size(c.Writer.Size()) //nolint:gosec // Finally, write log entry with status text + body size. l.Logf(lvl, "%s: wrote %s", statusText, size) diff --git a/internal/middleware/requestid.go b/internal/middleware/requestid.go index 00b1ff299..3ed3c1a98 100644 --- a/internal/middleware/requestid.go +++ b/internal/middleware/requestid.go @@ -48,7 +48,7 @@ func NewRequestID() string { b := make([]byte, 12) // Get current time in milliseconds. - ms := uint64(time.Now().UnixMilli()) + ms := uint64(time.Now().UnixMilli()) //nolint:gosec // Store binary time data in byte buffer. binary.LittleEndian.PutUint64(b[0:8], ms) diff --git a/internal/middleware/throttling.go b/internal/middleware/throttling.go index 33f46f175..fb5a0f1ef 100644 --- a/internal/middleware/throttling.go +++ b/internal/middleware/throttling.go @@ -87,7 +87,7 @@ func Throttle(cpuMultiplier int, retryAfter time.Duration) gin.HandlerFunc { queueLimit = limit * cpuMultiplier tokens = make(chan token, limit) requestCount = atomic.Int64{} - retryAfterStr = strconv.FormatUint(uint64(retryAfter/time.Second), 10) + retryAfterStr = strconv.FormatUint(uint64(retryAfter/time.Second), 10) //nolint:gosec ) // prefill token channel diff --git a/internal/processing/account/update.go b/internal/processing/account/update.go index 58e52a992..4aa3f781d 100644 --- a/internal/processing/account/update.go +++ b/internal/processing/account/update.go @@ -465,7 +465,7 @@ func (p *Processor) UpdateAvatar( maxsz := config.GetMediaLocalMaxSize() // Ensure media within size bounds. - if avatar.Size > int64(maxsz) { + if avatar.Size > int64(maxsz) { //nolint:gosec text := fmt.Sprintf("media exceeds configured max size: %s", maxsz) return nil, gtserror.NewErrorBadRequest(errors.New(text), text) } @@ -478,7 +478,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, int64(maxsz)) //nolint:gosec // Write to instance storage. return p.c.StoreLocalMedia(ctx, @@ -510,7 +510,7 @@ func (p *Processor) UpdateHeader( maxsz := config.GetMediaLocalMaxSize() // Ensure media within size bounds. - if header.Size > int64(maxsz) { + if header.Size > int64(maxsz) { //nolint:gosec text := fmt.Sprintf("media exceeds configured max size: %s", maxsz) return nil, gtserror.NewErrorBadRequest(errors.New(text), text) } @@ -523,7 +523,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, int64(maxsz)) //nolint:gosec // 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..20ee1a3e0 100644 --- a/internal/processing/admin/emoji.go +++ b/internal/processing/admin/emoji.go @@ -48,7 +48,7 @@ func (p *Processor) EmojiCreate( maxsz := config.GetMediaEmojiLocalMaxSize() // Ensure media within size bounds. - if form.Image.Size > int64(maxsz) { + if form.Image.Size > int64(maxsz) { //nolint:gosec text := fmt.Sprintf("emoji exceeds configured max size: %s", 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, int64(maxsz)) //nolint:gosec data := func(context.Context) (io.ReadCloser, error) { return rc, nil } @@ -303,7 +303,7 @@ func (p *Processor) emojiUpdateCopy( maxsz := config.GetMediaEmojiLocalMaxSize() // Ensure target emoji image within size bounds. - if bytesize.Size(target.ImageFileSize) > maxsz { + if bytesize.Size(target.ImageFileSize) > maxsz { //nolint:gosec text := fmt.Sprintf("emoji exceeds configured max size: %s", maxsz) return nil, gtserror.NewErrorBadRequest(errors.New(text), text) } @@ -444,7 +444,7 @@ func (p *Processor) emojiUpdateModify( maxsz := config.GetMediaEmojiLocalMaxSize() // Ensure media within size bounds. - if image.Size > int64(maxsz) { + if image.Size > int64(maxsz) { //nolint:gosec text := fmt.Sprintf("emoji exceeds configured max size: %s", 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, int64(maxsz)) //nolint:gosec 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..baee9115e 100644 --- a/internal/processing/media/create.go +++ b/internal/processing/media/create.go @@ -38,7 +38,7 @@ func (p *Processor) Create(ctx context.Context, account *gtsmodel.Account, form maxsz := config.GetMediaLocalMaxSize() // Ensure media within size bounds. - if form.File.Size > int64(maxsz) { + if form.File.Size > int64(maxsz) { //nolint:gosec text := fmt.Sprintf("media exceeds configured max size: %s", 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, int64(maxsz)) //nolint:gosec // Create local media and write to instance storage. attachment, errWithCode := p.c.StoreLocalMedia(ctx, diff --git a/internal/transport/derefmedia.go b/internal/transport/derefmedia.go index 873032f39..3a05fcbd6 100644 --- a/internal/transport/derefmedia.go +++ b/internal/transport/derefmedia.go @@ -53,7 +53,7 @@ func (t *transport) DereferenceMedia(ctx context.Context, iri *url.URL, maxsz in // Check media within size limit. if rsp.ContentLength > maxsz { _ = rsp.Body.Close() // close early. - sz := bytesize.Size(maxsz) // nicer log format + sz := bytesize.Size(maxsz) //nolint:gosec return nil, gtserror.Newf("media body exceeds max size %s", sz) } diff --git a/internal/typeutils/internaltofrontend.go b/internal/typeutils/internaltofrontend.go index 3b94687dc..e9884bf58 100644 --- a/internal/typeutils/internaltofrontend.go +++ b/internal/typeutils/internaltofrontend.go @@ -647,7 +647,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: int(util.PtrOrZero(media.FileMeta.Original.Bitrate)), //nolint:gosec } // Copy over local file URL. @@ -1529,9 +1529,9 @@ func (c *Converter) InstanceToAPIV1Instance(ctx context.Context, i *gtsmodel.Ins Version: config.GetSoftwareVersion(), Languages: config.GetInstanceLanguages().TagStrs(), Registrations: config.GetAccountsRegistrationOpen(), - ApprovalRequired: true, // approval always required - InvitesEnabled: false, // todo: not supported yet - MaxTootChars: uint(config.GetStatusesMaxChars()), + ApprovalRequired: true, // approval always required + InvitesEnabled: false, // todo: not supported yet + MaxTootChars: uint(config.GetStatusesMaxChars()), //nolint:gosec Rules: c.InstanceRulesToAPIRules(i.Rules), Terms: i.Terms, TermsRaw: i.TermsText, @@ -1551,9 +1551,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()) //nolint:gosec instance.Configuration.MediaAttachments.ImageMatrixLimit = instanceMediaAttachmentsImageMatrixLimit - instance.Configuration.MediaAttachments.VideoSizeLimit = int(config.GetMediaRemoteMaxSize()) + instance.Configuration.MediaAttachments.VideoSizeLimit = int(config.GetMediaRemoteMaxSize()) //nolint:gosec instance.Configuration.MediaAttachments.VideoFrameRateLimit = instanceMediaAttachmentsVideoFrameRateLimit instance.Configuration.MediaAttachments.VideoMatrixLimit = instanceMediaAttachmentsVideoMatrixLimit instance.Configuration.Polls.MaxOptions = config.GetStatusesPollMaxOptions() @@ -1563,7 +1563,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()) //nolint:gosec instance.Configuration.OIDCEnabled = config.GetOIDCEnabled() // URLs @@ -1695,9 +1695,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()) //nolint:gosec instance.Configuration.MediaAttachments.ImageMatrixLimit = instanceMediaAttachmentsImageMatrixLimit - instance.Configuration.MediaAttachments.VideoSizeLimit = int(config.GetMediaRemoteMaxSize()) + instance.Configuration.MediaAttachments.VideoSizeLimit = int(config.GetMediaRemoteMaxSize()) //nolint:gosec instance.Configuration.MediaAttachments.VideoFrameRateLimit = instanceMediaAttachmentsVideoFrameRateLimit instance.Configuration.MediaAttachments.VideoMatrixLimit = instanceMediaAttachmentsVideoMatrixLimit instance.Configuration.Polls.MaxOptions = config.GetStatusesPollMaxOptions() @@ -1707,7 +1707,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()) //nolint:gosec instance.Configuration.OIDCEnabled = config.GetOIDCEnabled() // registrations From fe5849fcf1d4db747d3ea24cb35e4f53e33daa93 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sat, 12 Oct 2024 10:33:00 +0200 Subject: [PATCH 08/15] fix golangci-lint documentation link --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cd0df69d7..36d51d245 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -385,7 +385,7 @@ We use [golangci-lint](https://golangci-lint.run/) for linting, which allows us If you make a PR that doesn't pass the linter, it will be rejected. As such, it's good practice to run the linter locally before pushing or opening a PR. -To do this, first install the linter following the instructions [here](https://golangci-lint.run/usage/install/#local-installation). +To do this, first install the linter following the instructions [here](https://golangci-lint.run/welcome/install/). Then, you can run the linter with: From a4f6f1474e41db700f092c36db5408a0096127b5 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sat, 12 Oct 2024 10:41:55 +0200 Subject: [PATCH 09/15] revert unrelated changes --- .drone.yml | 12 ++++++------ .goreleaser.yml | 5 ++--- Dockerfile | 4 ++-- go.mod | 2 +- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/.drone.yml b/.drone.yml index a4bb57332..5ae306b69 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.60.3 + image: golangci/golangci-lint:v1.57.2 volumes: - name: go-build-cache path: /root/.cache/go-build @@ -28,7 +28,7 @@ steps: - pull_request - name: test - image: golang:1.23.0-alpine + image: golang:1.22-alpine volumes: - name: go-build-cache path: /root/.cache/go-build @@ -94,7 +94,7 @@ steps: - pull_request - name: snapshot - image: superseriousbusiness/gotosocial-drone-build:0.7.0 # https://github.com/superseriousbusiness/gotosocial-drone-build + image: superseriousbusiness/gotosocial-drone-build:0.6.1 # https://github.com/superseriousbusiness/gotosocial-drone-build volumes: - name: go-build-cache path: /root/.cache/go-build @@ -141,7 +141,7 @@ steps: - main - name: release - image: superseriousbusiness/gotosocial-drone-build:0.7.0 # https://github.com/superseriousbusiness/gotosocial-drone-build + image: superseriousbusiness/gotosocial-drone-build:0.6.1 # https://github.com/superseriousbusiness/gotosocial-drone-build volumes: - name: go-build-cache path: /root/.cache/go-build @@ -200,7 +200,7 @@ clone: steps: - name: mirror - image: superseriousbusiness/gotosocial-drone-build:0.7.0 + image: superseriousbusiness/gotosocial-drone-build:0.6.1 environment: ORIGIN_REPO: https://github.com/superseriousbusiness/gotosocial TARGET_REPO: https://codeberg.org/superseriousbusiness/gotosocial @@ -213,6 +213,6 @@ steps: --- kind: signature -hmac: 9810bf692fb1029c13b0a1e2f556e2306d16f7d3eec9ca6163a0499c147280c1 +hmac: 475acfffed0cc2d45304f253cc8e57c6c19b8437571ec7e343a2ef85a7a270b8 ... diff --git a/.goreleaser.yml b/.goreleaser.yml index bfa700cc5..c43e8e085 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -1,5 +1,4 @@ -# Version 2 of GoReleaser: https://goreleaser.com/errors/version/ -version: 2 +# https://goreleaser.com project_name: gotosocial before: # https://goreleaser.com/customization/hooks/ @@ -391,7 +390,7 @@ checksum: name_template: 'checksums.txt' snapshot: # https://goreleaser.com/customization/snapshots/ - version_template: "{{ incpatch .Version }}-SNAPSHOT" + name_template: "{{ incpatch .Version }}-SNAPSHOT" source: # https://goreleaser.com/customization/source/ enabled: true diff --git a/Dockerfile b/Dockerfile index c59fc1662..9ca0b2a28 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.23.0-alpine AS swagger +FROM --platform=${BUILDPLATFORM} golang:1.22-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.20.2 as executor +FROM --platform=${TARGETPLATFORM} alpine:3.19.1 as executor # switch to non-root user:group for GtS USER 1000:1000 diff --git a/go.mod b/go.mod index b1311089d..10d7e4af6 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/superseriousbusiness/gotosocial -go 1.23 +go 1.22.2 replace modernc.org/sqlite => gitlab.com/NyaaaWhatsUpDoc/sqlite v1.33.1-concurrency-workaround From 77736957ecfb06b3893b8673f964c75503b32f34 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sat, 12 Oct 2024 10:43:27 +0200 Subject: [PATCH 10/15] revert another unrelated change --- internal/db/bundb/bundb.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/internal/db/bundb/bundb.go b/internal/db/bundb/bundb.go index 5ec51aa9c..e043c6dad 100644 --- a/internal/db/bundb/bundb.go +++ b/internal/db/bundb/bundb.go @@ -408,12 +408,13 @@ 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) { - // If database URL is defined, ignore - // other DB-related configuration fields. - if url := config.GetDbPostgresConnectionString(); url != "" { - return pgx.ParseConfig(url) - } + url := config.GetDbPostgresConnectionString() + // if database URL is defined, ignore other DB related configuration fields + if url != "" { + cfg, err := pgx.ParseConfig(url) + return cfg, err + } // these are all optional, the db adapter figures out defaults address := config.GetDbAddress() From bd9ce6638ec9daa5c658e6b29841ea32f7d3287e Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sat, 12 Oct 2024 10:54:08 +0200 Subject: [PATCH 11/15] get rid of remaining nolint:gosec --- internal/media/util.go | 2 +- internal/middleware/logger.go | 2 +- internal/middleware/requestid.go | 2 +- internal/middleware/throttling.go | 6 +++++- internal/processing/admin/emoji.go | 7 +++---- internal/typeutils/internaltofrontend.go | 2 +- 6 files changed, 12 insertions(+), 9 deletions(-) diff --git a/internal/media/util.go b/internal/media/util.go index f05573bd9..f6bf06260 100644 --- a/internal/media/util.go +++ b/internal/media/util.go @@ -145,7 +145,7 @@ func drainToTmp(rc io.ReadCloser) (string, error) { // Check to see if limit was reached, // (produces more useful error messages). if lr != nil && lr.N <= 0 { - err := fmt.Errorf("reached read limit %s", bytesize.Size(limit)) //nolint:gosec + err := fmt.Errorf("reached read limit %s", bytesize.Size(limit)) // #nosec G115 -- Just logging return path, gtserror.SetLimitReached(err) } diff --git a/internal/middleware/logger.go b/internal/middleware/logger.go index b21b4d072..da5be9dfa 100644 --- a/internal/middleware/logger.go +++ b/internal/middleware/logger.go @@ -123,7 +123,7 @@ func Logger(logClientIP bool) gin.HandlerFunc { } // Generate a nicer looking bytecount - size := bytesize.Size(c.Writer.Size()) //nolint:gosec + size := bytesize.Size(c.Writer.Size()) // #nosec G115 -- Just logging // Finally, write log entry with status text + body size. l.Logf(lvl, "%s: wrote %s", statusText, size) diff --git a/internal/middleware/requestid.go b/internal/middleware/requestid.go index 3ed3c1a98..7d98787a7 100644 --- a/internal/middleware/requestid.go +++ b/internal/middleware/requestid.go @@ -48,7 +48,7 @@ func NewRequestID() string { b := make([]byte, 12) // Get current time in milliseconds. - ms := uint64(time.Now().UnixMilli()) //nolint:gosec + ms := uint64(time.Now().UnixMilli()) // #nosec G115 -- Pre-1970 clock? // Store binary time data in byte buffer. binary.LittleEndian.PutUint64(b[0:8], ms) diff --git a/internal/middleware/throttling.go b/internal/middleware/throttling.go index fb5a0f1ef..739189b79 100644 --- a/internal/middleware/throttling.go +++ b/internal/middleware/throttling.go @@ -82,12 +82,16 @@ func Throttle(cpuMultiplier int, retryAfter time.Duration) gin.HandlerFunc { return func(c *gin.Context) {} } + if retryAfter < 0 { + retryAfter = 0 + } + var ( limit = runtime.GOMAXPROCS(0) * cpuMultiplier queueLimit = limit * cpuMultiplier tokens = make(chan token, limit) requestCount = atomic.Int64{} - retryAfterStr = strconv.FormatUint(uint64(retryAfter/time.Second), 10) //nolint:gosec + retryAfterStr = strconv.FormatUint(uint64(retryAfter/time.Second), 10) // #nosec G115 -- Checked right above ) // prefill token channel diff --git a/internal/processing/admin/emoji.go b/internal/processing/admin/emoji.go index b5ed66eed..03e8b486b 100644 --- a/internal/processing/admin/emoji.go +++ b/internal/processing/admin/emoji.go @@ -25,7 +25,6 @@ "mime/multipart" "strings" - "codeberg.org/gruf/go-bytesize" "codeberg.org/gruf/go-iotools" apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" "github.com/superseriousbusiness/gotosocial/internal/config" @@ -300,11 +299,11 @@ func (p *Processor) emojiUpdateCopy( } // Get maximum supported local emoji size. - maxsz := config.GetMediaEmojiLocalMaxSize() + maxsz := int(config.GetMediaEmojiLocalMaxSize()) // #nosec G115 -- Already validated // Ensure target emoji image within size bounds. - if bytesize.Size(target.ImageFileSize) > maxsz { //nolint:gosec - text := fmt.Sprintf("emoji exceeds configured max size: %s", maxsz) + if target.ImageFileSize > maxsz { + text := fmt.Sprintf("emoji exceeds configured max size: %d", maxsz) return nil, gtserror.NewErrorBadRequest(errors.New(text), text) } diff --git a/internal/typeutils/internaltofrontend.go b/internal/typeutils/internaltofrontend.go index 9e073aecf..1e20455c3 100644 --- a/internal/typeutils/internaltofrontend.go +++ b/internal/typeutils/internaltofrontend.go @@ -1531,7 +1531,7 @@ func (c *Converter) InstanceToAPIV1Instance(ctx context.Context, i *gtsmodel.Ins Registrations: config.GetAccountsRegistrationOpen(), ApprovalRequired: true, // approval always required InvitesEnabled: false, // todo: not supported yet - MaxTootChars: uint(config.GetStatusesMaxChars()), //nolint:gosec + MaxTootChars: uint(config.GetStatusesMaxChars()), // #nosec G115 -- Already validated. Rules: c.InstanceRulesToAPIRules(i.Rules), Terms: i.Terms, TermsRaw: i.TermsText, From 9b1683bee6e560305edbf1c0e3128659680b7379 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sat, 12 Oct 2024 12:06:59 +0200 Subject: [PATCH 12/15] swagger updates --- docs/api/swagger.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/swagger.yaml b/docs/api/swagger.yaml index 1a5dd1fc3..ee2fb5974 100644 --- a/docs/api/swagger.yaml +++ b/docs/api/swagger.yaml @@ -2114,7 +2114,7 @@ definitions: bitrate: description: Bitrate of the media in bits per second. example: 1000000 - format: int64 + format: uint64 type: integer x-go-name: Bitrate duration: From 263ddf8128d7cbfeac0b1f01fc6349dba3840472 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sat, 12 Oct 2024 12:59:19 +0200 Subject: [PATCH 13/15] apply review feedback --- internal/media/ffmpeg.go | 13 ++----------- internal/processing/admin/emoji.go | 25 ++++++++++++++----------- internal/processing/media/create.go | 9 +++++---- 3 files changed, 21 insertions(+), 26 deletions(-) diff --git a/internal/media/ffmpeg.go b/internal/media/ffmpeg.go index 6d174bdbc..f1c277934 100644 --- a/internal/media/ffmpeg.go +++ b/internal/media/ffmpeg.go @@ -21,7 +21,6 @@ "context" "encoding/json" "errors" - "math" "os" "path" "strconv" @@ -557,18 +556,10 @@ 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) - - 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. + num, den = uint32(n), uint32(d) // #nosec G115 -- ParseUint is configured to check } else { n, _ := strconv.ParseUint(p[0], 10, 32) - - if n > math.MaxUint32 { - return nil, gtserror.Newf("overflowed numerator") - } - num = uint32(n) // #nosec G115 -- Just checked. + num = uint32(n) // #nosec G115 -- ParseUint is configured to check } // Set final divised framerate. diff --git a/internal/processing/admin/emoji.go b/internal/processing/admin/emoji.go index 03e8b486b..5a7da445e 100644 --- a/internal/processing/admin/emoji.go +++ b/internal/processing/admin/emoji.go @@ -44,11 +44,12 @@ func (p *Processor) EmojiCreate( ) (*apimodel.Emoji, gtserror.WithCode) { // Get maximum supported local emoji size. - maxsz := int64(config.GetMediaEmojiLocalMaxSize()) // #nosec G115 -- Already validated. + maxsz := config.GetMediaEmojiLocalMaxSize() + maxszInt64 := int64(maxsz) // #nosec G115 -- Already validated. // Ensure media within size bounds. - if form.Image.Size > maxsz { - text := fmt.Sprintf("emoji exceeds configured max size: %d", maxsz) + if form.Image.Size > maxszInt64 { + text := fmt.Sprintf("emoji exceeds configured max size: %s", maxsz) return nil, gtserror.NewErrorBadRequest(errors.New(text), text) } @@ -60,7 +61,7 @@ func (p *Processor) EmojiCreate( } // Wrap the multipart file reader to ensure is limited to max. - rc, _, _ := iotools.UpdateReadCloserLimit(mpfile, maxsz) + rc, _, _ := iotools.UpdateReadCloserLimit(mpfile, maxszInt64) data := func(context.Context) (io.ReadCloser, error) { return rc, nil } @@ -299,11 +300,12 @@ func (p *Processor) emojiUpdateCopy( } // Get maximum supported local emoji size. - maxsz := int(config.GetMediaEmojiLocalMaxSize()) // #nosec G115 -- Already validated + maxsz := config.GetMediaEmojiLocalMaxSize() + maxszInt := int(maxsz) // #nosec G115 -- Already validated. // Ensure target emoji image within size bounds. - if target.ImageFileSize > maxsz { - text := fmt.Sprintf("emoji exceeds configured max size: %d", maxsz) + if target.ImageFileSize > maxszInt { + text := fmt.Sprintf("emoji exceeds configured max size: %s", maxsz) return nil, gtserror.NewErrorBadRequest(errors.New(text), text) } @@ -440,11 +442,12 @@ func (p *Processor) emojiUpdateModify( // We can do both at the same time :) // Get maximum supported local emoji size. - maxsz := int64(config.GetMediaEmojiLocalMaxSize()) // #nosec G115 -- Already validated. + maxsz := config.GetMediaEmojiLocalMaxSize() + maxszInt64 := int64(maxsz) // #nosec G115 -- Already validated. // Ensure media within size bounds. - if image.Size > maxsz { - text := fmt.Sprintf("emoji exceeds configured max size: %d", maxsz) + if image.Size > maxszInt64 { + text := fmt.Sprintf("emoji exceeds configured max size: %s", maxsz) return nil, gtserror.NewErrorBadRequest(errors.New(text), text) } @@ -456,7 +459,7 @@ func (p *Processor) emojiUpdateModify( } // Wrap the multipart file reader to ensure is limited to max. - rc, _, _ := iotools.UpdateReadCloserLimit(mpfile, maxsz) + rc, _, _ := iotools.UpdateReadCloserLimit(mpfile, int64(maxsz)) // #nosec G115 -- Already validated. 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 64e44d999..ca1f1c3c6 100644 --- a/internal/processing/media/create.go +++ b/internal/processing/media/create.go @@ -35,11 +35,12 @@ func (p *Processor) Create(ctx context.Context, account *gtsmodel.Account, form *apimodel.AttachmentRequest) (*apimodel.Attachment, gtserror.WithCode) { // Get maximum supported local media size. - maxsz := int64(config.GetMediaLocalMaxSize()) // #nosec G115 -- Already validated. + maxsz := config.GetMediaLocalMaxSize() + maxszInt64 := int64(maxsz) // #nosec G115 -- Already validated. // Ensure media within size bounds. - if form.File.Size > maxsz { - text := fmt.Sprintf("media exceeds configured max size: %d", maxsz) + if form.File.Size > maxszInt64 { + text := fmt.Sprintf("media exceeds configured max size: %s", maxsz) return nil, gtserror.NewErrorBadRequest(errors.New(text), text) } @@ -58,7 +59,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, maxsz) + rc, _, _ := iotools.UpdateReadCloserLimit(mpfile, maxszInt64) // Create local media and write to instance storage. attachment, errWithCode := p.c.StoreLocalMedia(ctx, From 3d407b556e041f8ea1ce6a6967509fff03a939a6 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sat, 12 Oct 2024 13:03:28 +0200 Subject: [PATCH 14/15] fix wrong formatting specifier thing --- internal/processing/account/update.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/processing/account/update.go b/internal/processing/account/update.go index a21b0c9d2..285f822dd 100644 --- a/internal/processing/account/update.go +++ b/internal/processing/account/update.go @@ -466,7 +466,7 @@ func (p *Processor) UpdateAvatar( // Ensure media within size bounds. if avatar.Size > maxsz { - text := fmt.Sprintf("media exceeds configured max size: %d", maxsz) + text := fmt.Sprintf("media exceeds configured max size: %s", maxsz) return nil, gtserror.NewErrorBadRequest(errors.New(text), text) } @@ -511,7 +511,7 @@ func (p *Processor) UpdateHeader( // Ensure media within size bounds. if header.Size > maxsz { - text := fmt.Sprintf("media exceeds configured max size: %d", maxsz) + text := fmt.Sprintf("media exceeds configured max size: %s", maxsz) return nil, gtserror.NewErrorBadRequest(errors.New(text), text) } From 79fb292246b44fde07edf8aa8667ae94ca07d367 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sat, 12 Oct 2024 13:10:01 +0200 Subject: [PATCH 15/15] fix the linter for real --- internal/processing/account/update.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/internal/processing/account/update.go b/internal/processing/account/update.go index 285f822dd..2bdbf96f4 100644 --- a/internal/processing/account/update.go +++ b/internal/processing/account/update.go @@ -462,10 +462,11 @@ func (p *Processor) UpdateAvatar( gtserror.WithCode, ) { // Get maximum supported local media size. - maxsz := int64(config.GetMediaLocalMaxSize()) // #nosec G115 -- Already validated. + maxsz := config.GetMediaLocalMaxSize() + maxszInt64 := int64(maxsz) // #nosec G115 -- Already validated. // Ensure media within size bounds. - if avatar.Size > maxsz { + if avatar.Size > maxszInt64 { text := fmt.Sprintf("media exceeds configured max size: %s", maxsz) return nil, gtserror.NewErrorBadRequest(errors.New(text), text) } @@ -478,7 +479,7 @@ func (p *Processor) UpdateAvatar( } // Wrap the multipart file reader to ensure is limited to max. - rc, _, _ := iotools.UpdateReadCloserLimit(mpfile, maxsz) + rc, _, _ := iotools.UpdateReadCloserLimit(mpfile, maxszInt64) // Write to instance storage. return p.c.StoreLocalMedia(ctx, @@ -507,10 +508,11 @@ func (p *Processor) UpdateHeader( gtserror.WithCode, ) { // Get maximum supported local media size. - maxsz := int64(config.GetMediaLocalMaxSize()) // #nosec G115 -- Already validated. + maxsz := config.GetMediaLocalMaxSize() + maxszInt64 := int64(maxsz) // #nosec G115 -- Already validated. // Ensure media within size bounds. - if header.Size > maxsz { + if header.Size > maxszInt64 { text := fmt.Sprintf("media exceeds configured max size: %s", maxsz) return nil, gtserror.NewErrorBadRequest(errors.New(text), text) } @@ -523,7 +525,7 @@ func (p *Processor) UpdateHeader( } // Wrap the multipart file reader to ensure is limited to max. - rc, _, _ := iotools.UpdateReadCloserLimit(mpfile, maxsz) + rc, _, _ := iotools.UpdateReadCloserLimit(mpfile, maxszInt64) // Write to instance storage. return p.c.StoreLocalMedia(ctx,