From 7d0af7624c6924f6c24c4c5b623e2257addd0f6a Mon Sep 17 00:00:00 2001 From: Jakub Date: Wed, 7 Apr 2021 09:19:22 +0200 Subject: [PATCH] Other: Bump linter --- .golangci.yml | 61 +++++++++++++++++++---- Makefile | 2 +- internal/config/settings/settings.go | 2 +- internal/config/tls/tls.go | 1 + internal/frontend/cli-ie/accounts.go | 2 +- internal/frontend/cli/accounts.go | 2 +- internal/frontend/cli/system.go | 2 +- internal/imap/bridge.go | 4 +- internal/imap/store.go | 6 +-- internal/imap/uidplus/extension.go | 4 +- internal/logging/crash.go | 2 +- internal/smtp/bridge.go | 2 +- internal/transfer/provider_imap_utils.go | 6 +-- internal/transfer/provider_mbox_target.go | 2 +- internal/updater/sync.go | 6 +-- pkg/pmapi/bugs.go | 6 +-- pkg/pmapi/client.go | 2 +- pkg/pmapi/contacts.go | 8 +-- pkg/pmapi/message_send.go | 2 +- pkg/srp/hash.go | 6 +-- pkg/tar/tar.go | 31 +++++++++++- test/context/settings.go | 4 +- 22 files changed, 116 insertions(+), 47 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 31d42525..7da404d7 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,3 +1,4 @@ +--- run: timeout: 10m build-tags: @@ -8,9 +9,11 @@ run: issues: exclude-use-default: false exclude: - - Using the variable on range scope `tt` in function literal - - should have comment (\([^)]+\) )?or be unexported # For now we are missing a lot of comments. - - at least one file in a package should have a package comment # For now we are missing a lot of comments. + - Using the variable on range scope `tt` in function literal + # For now we are missing a lot of comments. + - should have comment (\([^)]+\) )?or be unexported + # For now we are missing a lot of comments. + - at least one file in a package should have a package comment exclude-rules: - path: _test\.go @@ -30,7 +33,7 @@ linters-settings: linters: # setting disable-all will make only explicitly enabled linters run disable-all: true - + enable: - deadcode # Finds unused code [fast: true, auto-fix: false] - errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases [fast: true, auto-fix: false] @@ -49,7 +52,7 @@ linters: - funlen # Tool for detection of long functions [fast: true, auto-fix: false] - gochecknoglobals # Checks that no globals are present in Go code [fast: true, auto-fix: false] - gochecknoinits # Checks that no init functions are present in Go code [fast: true, auto-fix: false] - #- gocognit # Computes and checks the cognitive complexity of functions [fast: true, auto-fix: false] + # - gocognit # Computes and checks the cognitive complexity of functions [fast: true, auto-fix: false] - goconst # Finds repeated strings that could be replaced by a constant [fast: true, auto-fix: false] - gocritic # The most opinionated Go source code linter [fast: true, auto-fix: false] - gocyclo # Computes and checks the cyclomatic complexity of functions [fast: true, auto-fix: false] @@ -58,15 +61,53 @@ linters: - goimports # Goimports does everything that gofmt does. Additionally it checks unused imports [fast: true, auto-fix: true] - golint # Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes [fast: true, auto-fix: false] - gosec # Inspects source code for security problems [fast: true, auto-fix: false] - - interfacer # Linter that suggests narrower interface types [fast: true, auto-fix: false] - - maligned # Tool to detect Go structs that would take less memory if their fields were sorted [fast: true, auto-fix: false] - misspell # Finds commonly misspelled English words in comments [fast: true, auto-fix: true] - nakedret # Finds naked returns in functions greater than a specified function length [fast: true, auto-fix: false] - prealloc # Finds slice declarations that could potentially be preallocated [fast: true, auto-fix: false] - - scopelint # Scopelint checks for unpinned variables in go programs [fast: true, auto-fix: false] - stylecheck # Stylecheck is a replacement for golint [fast: true, auto-fix: false] - unconvert # Remove unnecessary type conversions [fast: true, auto-fix: false] - unparam # Reports unused function parameters [fast: true, auto-fix: false] - whitespace # Tool for detection of leading and trailing whitespace [fast: true, auto-fix: true] - #- wsl # Whitespace Linter - Forces you to use empty lines! [fast: true, auto-fix: false] - #- lll # Reports long lines [fast: true, auto-fix: false] + # - wsl # Whitespace Linter - Forces you to use empty lines! [fast: true, auto-fix: false] + # - lll # Reports long lines [fast: true, auto-fix: false] + # Newly added linters (not processed yet) + # - asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers [fast: true, auto-fix: false] + # - cyclop # checks function and package cyclomatic complexity [fast: false, auto-fix: false] + # - durationcheck # check for two durations multiplied together [fast: false, auto-fix: false] + # - errorlint # go-errorlint is a source code linter for Go software that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13. [fast: false, auto-fix: false] + # - exhaustive # check exhaustiveness of enum switch statements [fast: false, auto-fix: false] + # - exhaustivestruct # Checks if all struct's fields are initialized [fast: false, auto-fix: false] + # - exportloopref # checks for pointers to enclosing loop variables [fast: false, auto-fix: false] + # - forbidigo # Forbids identifiers [fast: true, auto-fix: false] + # - forcetypeassert # finds forced type assertions [fast: true, auto-fix: false] + # - gci # Gci control golang package import order and make it always deterministic. [fast: true, auto-fix: true] + # - gocognit # Computes and checks the cognitive complexity of functions [fast: true, auto-fix: false] + # - godot # Check if comments end in a period [fast: true, auto-fix: true] + # - goerr113 # Golang linter to check the errors handling expressions [fast: false, auto-fix: false] + # - gofumpt # Gofumpt checks whether code was gofumpt-ed. [fast: true, auto-fix: true] + # - goheader # Checks is file header matches to pattern [fast: true, auto-fix: false] + # - gomnd # An analyzer to detect magic numbers. [fast: true, auto-fix: false] + # - gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. [fast: true, auto-fix: false] + # - gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. [fast: true, auto-fix: false] + # - goprintffuncname # Checks that printf-like functions are named with `f` at the end [fast: true, auto-fix: false] + # - ifshort # Checks that your code uses short syntax for if-statements whenever possible [fast: true, auto-fix: false] + # - importas # Enforces consistent import aliases [fast: false, auto-fix: false] + # - lll # Reports long lines [fast: true, auto-fix: false] + # - makezero # Finds slice declarations with non-zero initial length [fast: false, auto-fix: false] + # - nestif # Reports deeply nested if statements [fast: true, auto-fix: false] + # - nilerr # Finds the code that returns nil even if it checks that the error is not nil. [fast: false, auto-fix: false] + # - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity [fast: true, auto-fix: false] + # - noctx # noctx finds sending http request without context.Context [fast: false, auto-fix: false] + # - nolintlint # Reports ill-formed or insufficient nolint directives [fast: true, auto-fix: false] + # - paralleltest # paralleltest detects missing usage of t.Parallel() method in your Go test [fast: true, auto-fix: false] + # - predeclared # find code that shadows one of Go's predeclared identifiers [fast: true, auto-fix: false] + # - revive # Fast, configurable, extensible, flexible, and beautiful linter for Go. Drop-in replacement of golint. [fast: false, auto-fix: false] + # - rowserrcheck # checks whether Err of rows is checked successfully [fast: false, auto-fix: false] + # - sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed. [fast: false, auto-fix: false] + # - testpackage # linter that makes you use a separate _test package [fast: true, auto-fix: false] + # - thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers [fast: false, auto-fix: false] + # - tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes [fast: false, auto-fix: false] + # - wastedassign # wastedassign finds wasted assignment statements. [fast: false, auto-fix: false] + # - wrapcheck # Checks that errors returned from external packages are wrapped [fast: false, auto-fix: false] + # - wsl # Whitespace Linter - Forces you to use empty lines! [fast: true, auto-fix: false] + diff --git a/Makefile b/Makefile index b6d6561a..5de16b78 100644 --- a/Makefile +++ b/Makefile @@ -188,7 +188,7 @@ update-qt-docs: ## Dev dependencies .PHONY: install-devel-tools install-linter install-go-mod-outdated install-git-hooks -LINTVER:="v1.29.0" +LINTVER:="v1.39.0" LINTSRC:="https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh" install-dev-dependencies: install-devel-tools install-linter install-go-mod-outdated diff --git a/internal/config/settings/settings.go b/internal/config/settings/settings.go index 09cdc344..aadaa183 100644 --- a/internal/config/settings/settings.go +++ b/internal/config/settings/settings.go @@ -78,7 +78,7 @@ func (s *Settings) setDefaultValues() { s.setDefault(ReportOutgoingNoEncKey, "false") s.setDefault(LastVersionKey, "") s.setDefault(UpdateChannelKey, "") - s.setDefault(RolloutKey, fmt.Sprintf("%v", rand.Float64())) + s.setDefault(RolloutKey, fmt.Sprintf("%v", rand.Float64())) //nolint[gosec] G404 It is OK to use weak random number generator here s.setDefault(PreferredKeychainKey, "") s.setDefault(APIPortKey, DefaultAPIPort) diff --git a/internal/config/tls/tls.go b/internal/config/tls/tls.go index 0ce76cd4..3203b46e 100644 --- a/internal/config/tls/tls.go +++ b/internal/config/tls/tls.go @@ -154,5 +154,6 @@ func (t *TLS) GetConfig() (*tls.Config, error) { ClientAuth: tls.VerifyClientCertIfGiven, RootCAs: caCertPool, ClientCAs: caCertPool, + MinVersion: tls.VersionTLS13, // gosec G402 }, nil } diff --git a/internal/frontend/cli-ie/accounts.go b/internal/frontend/cli-ie/accounts.go index c192c208..eb0d56ad 100644 --- a/internal/frontend/cli-ie/accounts.go +++ b/internal/frontend/cli-ie/accounts.go @@ -25,7 +25,7 @@ import ( func (f *frontendCLI) listAccounts(c *ishell.Context) { spacing := "%-2d: %-20s (%-15s, %-15s)\n" - f.Printf(bold(strings.Replace(spacing, "d", "s", -1)), "#", "account", "status", "address mode") + f.Printf(bold(strings.ReplaceAll(spacing, "d", "s")), "#", "account", "status", "address mode") for idx, user := range f.ie.GetUsers() { connected := "disconnected" if user.IsConnected() { diff --git a/internal/frontend/cli/accounts.go b/internal/frontend/cli/accounts.go index 8c3d1e51..4332a6f8 100644 --- a/internal/frontend/cli/accounts.go +++ b/internal/frontend/cli/accounts.go @@ -28,7 +28,7 @@ import ( func (f *frontendCLI) listAccounts(c *ishell.Context) { spacing := "%-2d: %-20s (%-15s, %-15s)\n" - f.Printf(bold(strings.Replace(spacing, "d", "s", -1)), "#", "account", "status", "address mode") + f.Printf(bold(strings.ReplaceAll(spacing, "d", "s")), "#", "account", "status", "address mode") for idx, user := range f.bridge.GetUsers() { connected := "disconnected" if user.IsConnected() { diff --git a/internal/frontend/cli/system.go b/internal/frontend/cli/system.go index 0b7396a0..74c64765 100644 --- a/internal/frontend/cli/system.go +++ b/internal/frontend/cli/system.go @@ -161,7 +161,7 @@ func (f *frontendCLI) disallowProxy(c *ishell.Context) { } func (f *frontendCLI) isPortFree(port string) bool { - port = strings.Replace(port, ":", "", -1) + port = strings.ReplaceAll(port, ":", "") if port == "" || port == currentPort { return true } diff --git a/internal/imap/bridge.go b/internal/imap/bridge.go index 2be46194..7f2ef36b 100644 --- a/internal/imap/bridge.go +++ b/internal/imap/bridge.go @@ -61,7 +61,7 @@ func (b *bridgeWrap) GetUser(query string) (bridgeUser, error) { if err != nil { return nil, err } - return newBridgeUserWrap(user), nil + return newBridgeUserWrap(user), nil //nolint[typecheck] missing methods are inherited } type bridgeUserWrap struct { @@ -77,5 +77,5 @@ func (u *bridgeUserWrap) GetStore() storeUserProvider { if store == nil { return nil } - return newStoreUserWrap(store) + return newStoreUserWrap(store) //nolint[typecheck] missing methods are inherited } diff --git a/internal/imap/store.go b/internal/imap/store.go index 83a6633a..1566ccba 100644 --- a/internal/imap/store.go +++ b/internal/imap/store.go @@ -123,7 +123,7 @@ func (s *storeUserWrap) GetAddress(addressID string) (storeAddressProvider, erro if err != nil { return nil, err } - return newStoreAddressWrap(address), nil + return newStoreAddressWrap(address), nil //nolint[typecheck] missing methods are inherited } type storeAddressWrap struct { @@ -137,7 +137,7 @@ func newStoreAddressWrap(address *store.Address) *storeAddressWrap { func (s *storeAddressWrap) ListMailboxes() []storeMailboxProvider { mailboxes := []storeMailboxProvider{} for _, mailbox := range s.Address.ListMailboxes() { - mailboxes = append(mailboxes, newStoreMailboxWrap(mailbox)) + mailboxes = append(mailboxes, newStoreMailboxWrap(mailbox)) //nolint[typecheck] missing methods are inherited } return mailboxes } @@ -147,7 +147,7 @@ func (s *storeAddressWrap) GetMailbox(name string) (storeMailboxProvider, error) if err != nil { return nil, err } - return newStoreMailboxWrap(mailbox), nil + return newStoreMailboxWrap(mailbox), nil //nolint[typecheck] missing methods are inherited } type storeMailboxWrap struct { diff --git a/internal/imap/uidplus/extension.go b/internal/imap/uidplus/extension.go index f3d1df39..db79ad5e 100644 --- a/internal/imap/uidplus/extension.go +++ b/internal/imap/uidplus/extension.go @@ -228,7 +228,7 @@ func getStatusResponseCopy(uidValidity uint32, sourceSeq, targetSeq *OrderedSeq) // CopyResponse prepares OK response with extended UID information about copied message. func CopyResponse(uidValidity uint32, sourceSeq, targetSeq *OrderedSeq) error { - return server.ErrStatusResp(getStatusResponseCopy(uidValidity, sourceSeq, targetSeq)) + return imap.ErrStatusResp{getStatusResponseCopy(uidValidity, sourceSeq, targetSeq)} } func getStatusResponseAppend(uidValidity uint32, targetSeq *OrderedSeq) *imap.StatusResp { @@ -250,5 +250,5 @@ func getStatusResponseAppend(uidValidity uint32, targetSeq *OrderedSeq) *imap.St // AppendResponse prepares OK response with extended UID information about appended message. func AppendResponse(uidValidity uint32, targetSeq *OrderedSeq) error { - return server.ErrStatusResp(getStatusResponseAppend(uidValidity, targetSeq)) + return imap.ErrStatusResp{getStatusResponseAppend(uidValidity, targetSeq)} } diff --git a/internal/logging/crash.go b/internal/logging/crash.go index 17917d0e..cc3c8a2c 100644 --- a/internal/logging/crash.go +++ b/internal/logging/crash.go @@ -34,7 +34,7 @@ func DumpStackTrace(logsPath string) crash.RecoveryAction { return func(r interface{}) error { file := filepath.Join(logsPath, getStackTraceName(constants.Version, constants.Revision)) - f, err := os.OpenFile(file, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0600) + f, err := os.OpenFile(filepath.Clean(file), os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0600) if err != nil { return err } diff --git a/internal/smtp/bridge.go b/internal/smtp/bridge.go index 08ed8b1f..af7e8c4d 100644 --- a/internal/smtp/bridge.go +++ b/internal/smtp/bridge.go @@ -51,7 +51,7 @@ func (b *bridgeWrap) GetUser(query string) (bridgeUser, error) { if err != nil { return nil, err } - return newBridgeUserWrap(user), nil + return newBridgeUserWrap(user), nil //nolint[typecheck] missing methods are inherited } type bridgeUserWrap struct { diff --git a/internal/transfer/provider_imap_utils.go b/internal/transfer/provider_imap_utils.go index c8d50782..68f87f09 100644 --- a/internal/transfer/provider_imap_utils.go +++ b/internal/transfer/provider_imap_utils.go @@ -62,10 +62,10 @@ func imapClientDial(addr string) (IMAPClientProvider, error) { client.ErrorLog = &imapErrorLogger{logrus.WithField("pkg", "imap-client")} // Logrus `WriterLevel` fails for big messages because of bufio.MaxScanTokenSize limit. // Also, this spams a lot, uncomment once needed during development. - //client.SetDebug(imap.NewDebugWriter( + // client.SetDebug(imap.NewDebugWriter( // logrus.WithField("pkg", "imap/client").WriterLevel(logrus.TraceLevel), // logrus.WithField("pkg", "imap/server").WriterLevel(logrus.TraceLevel), - //)) + // )) } return client, err } @@ -84,7 +84,7 @@ func imapClientDialHelper(addr string) (*imapClient.Client, error) { var tlsConf *tls.Config if strings.Contains(strings.ToLower(host), "yahoo") { log.Warning("Yahoo server detected: limiting maximal TLS version to 1.2.") - tlsConf = &tls.Config{MaxVersion: tls.VersionTLS12} + tlsConf = &tls.Config{MaxVersion: tls.VersionTLS12} //nolint[gosec] G402 } return imapClient.DialTLS(addr, tlsConf) } diff --git a/internal/transfer/provider_mbox_target.go b/internal/transfer/provider_mbox_target.go index c9da34d8..82f43018 100644 --- a/internal/transfer/provider_mbox_target.go +++ b/internal/transfer/provider_mbox_target.go @@ -63,7 +63,7 @@ func (p *MBOXProvider) writeMessage(msg Message) error { } mboxPath := filepath.Join(p.root, mboxName) - mboxFile, err := os.OpenFile(mboxPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600) + mboxFile, err := os.OpenFile(filepath.Clean(mboxPath), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600) if err != nil { multiErr = multierror.Append(multiErr, err) continue diff --git a/internal/updater/sync.go b/internal/updater/sync.go index d316cc74..4618c17e 100644 --- a/internal/updater/sync.go +++ b/internal/updater/sync.go @@ -125,7 +125,7 @@ func mkdirAllClear(path string) error { // checksum assumes the file is a regular file and that it exists. func checksum(path string) (hash string) { - file, err := os.Open(path) //nolint[gosec] + file, err := os.Open(filepath.Clean(path)) if err != nil { return } @@ -224,7 +224,7 @@ func copyRecursively(srcDir, dstDir string) error { // nolint[funlen] } // Create/overwrite regular file. - srcReader, err := os.Open(srcPath) //nolint[gosec] + srcReader, err := os.Open(filepath.Clean(srcPath)) if err != nil { return err } @@ -244,7 +244,7 @@ func copyToTmpFileRename(srcReader io.Reader, dstPath string, dstMode os.FileMod func copyToFileTruncate(srcReader io.Reader, dstPath string, dstMode os.FileMode) error { logrus.Debug("Copy and truncate ", dstPath) - dstWriter, err := os.OpenFile(dstPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, dstMode) + dstWriter, err := os.OpenFile(filepath.Clean(dstPath), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, dstMode) //nolint[gosec] Cannot guess the safe part of path if err != nil { return err } diff --git a/pkg/pmapi/bugs.go b/pkg/pmapi/bugs.go index 90dff003..9af23098 100644 --- a/pkg/pmapi/bugs.go +++ b/pkg/pmapi/bugs.go @@ -104,7 +104,7 @@ func writeMultipartReport(w *multipart.Writer, rep *ReportReq) error { // nolint fmt.Sprintf(`form-data; name="%s"; filename="%s"`, quoteEscaper.Replace(att.name), quoteEscaper.Replace(att.filename+".zip"))) h.Set("Content-Type", "application/octet-stream") - //h.Set("Content-Transfere-Encoding", "base64") + // h.Set("Content-Transfer-Encoding", "base64") attWr, err := w.CreatePart(h) if err != nil { return err @@ -112,7 +112,7 @@ func writeMultipartReport(w *multipart.Writer, rep *ReportReq) error { // nolint zipArch := zip.NewWriter(attWr) zipWr, err := zipArch.Create(att.filename) - //b64 := base64.NewEncoder(base64.StdEncoding, zipWr) + // b64 := base64.NewEncoder(base64.StdEncoding, zipWr) if err != nil { return err } @@ -121,7 +121,7 @@ func writeMultipartReport(w *multipart.Writer, rep *ReportReq) error { // nolint return err } err = zipArch.Close() - //err = b64.Close() + // err = b64.Close() if err != nil { return err } diff --git a/pkg/pmapi/client.go b/pkg/pmapi/client.go index 528a17e9..1df8b082 100644 --- a/pkg/pmapi/client.go +++ b/pkg/pmapi/client.go @@ -293,7 +293,7 @@ func (c *client) doBuffered(req *http.Request, bodyBuffer []byte, retryUnauthori retryAfter = headerAfter } // To avoid spikes when all clients retry at the same time, we add some random wait. - retryAfter += rand.Intn(10) + retryAfter += rand.Intn(10) //nolint[gosec] It is OK to use weak random number generator here if hasBody { r := bytes.NewReader(bodyBuffer) diff --git a/pkg/pmapi/contacts.go b/pkg/pmapi/contacts.go index 8efd30dd..89950812 100644 --- a/pkg/pmapi/contacts.go +++ b/pkg/pmapi/contacts.go @@ -60,7 +60,7 @@ type ContactEmail struct { var errVerificationFailed = errors.New("signature verification failed") -//================= Public utility functions ====================== +// ================= Public utility functions ====================== func (c *client) EncryptAndSignCards(cards []Card) ([]Card, error) { var err error @@ -105,7 +105,7 @@ func (c *client) DecryptAndVerifyCards(cards []Card) ([]Card, error) { return cards, nil } -//====================== READ =========================== +// ====================== READ =========================== type ContactsListRes struct { Res @@ -235,7 +235,7 @@ func (c *client) GetContactEmailByEmail(email string, page int, pageSize int) (c return } -//============================ CREATE ==================================== +// ============================ CREATE ==================================== type CardsList struct { Cards []Card @@ -419,7 +419,7 @@ func (c *client) DeleteAllContacts() (err error) { return } -//===================== Private utility methods ======================= +// ===================== Private utility methods ======================= func isSignedCardType(cardType int) bool { return (cardType & CardSigned) == CardSigned diff --git a/pkg/pmapi/message_send.go b/pkg/pmapi/message_send.go index 6736a8b0..30908197 100644 --- a/pkg/pmapi/message_send.go +++ b/pkg/pmapi/message_send.go @@ -137,7 +137,7 @@ func newMessagePackage( } type sendData struct { - decryptedBodyKey *crypto.SessionKey //body session key + decryptedBodyKey *crypto.SessionKey // body session key addressMap map[string]*MessageAddress sharedScheme PackageFlag ciphertext []byte diff --git a/pkg/srp/hash.go b/pkg/srp/hash.go index 8ffe2cb5..3800587f 100644 --- a/pkg/srp/hash.go +++ b/pkg/srp/hash.go @@ -70,9 +70,9 @@ func HashPassword(authVersion int, password, userName string, salt, modulus []by // CleanUserName returns the input string in lower-case without characters `_`, // `.` and `-`. func CleanUserName(userName string) string { - userName = strings.Replace(userName, "-", "", -1) - userName = strings.Replace(userName, ".", "", -1) - userName = strings.Replace(userName, "_", "", -1) + userName = strings.ReplaceAll(userName, "-", "") + userName = strings.ReplaceAll(userName, ".", "") + userName = strings.ReplaceAll(userName, "_", "") return strings.ToLower(userName) } diff --git a/pkg/tar/tar.go b/pkg/tar/tar.go index 3fda4a3a..53023adc 100644 --- a/pkg/tar/tar.go +++ b/pkg/tar/tar.go @@ -19,6 +19,7 @@ package tar import ( "archive/tar" + "errors" "io" "os" "path/filepath" @@ -27,6 +28,31 @@ import ( "github.com/sirupsen/logrus" ) +// maxFileSize limit tre single file size after decopression is not larger than 1GB +const maxFileSize = int64(1 * 1024 * 1024 * 1024) // 1 GB + +// ErrFileTooLarge returned when decompressed file is too large +var ErrFileTooLarge = errors.New("trying to decompress file larger than 1GB") + +type limitReader struct { + r io.Reader + n int64 +} + +// Read returns error if limit was exceeded. Inspired by io.LimitReader.Read +func (lr *limitReader) Read(p []byte) (n int, err error) { + if lr.n <= 0 { + return 0, ErrFileTooLarge + } + if int64(len(p)) > lr.n { + p = p[0:lr.n] + } + n, err = lr.r.Read(p) + lr.n -= int64(n) + return +} + +// UntarToDir decopmress and unarchive the files into directory func UntarToDir(r io.Reader, dir string) error { tr := tar.NewReader(r) @@ -42,7 +68,7 @@ func UntarToDir(r io.Reader, dir string) error { continue } - target := filepath.Join(dir, header.Name) + target := filepath.Join(dir, filepath.Clean(header.Name)) // gosec G305 switch { case header.Typeflag == tar.TypeSymlink: @@ -60,7 +86,8 @@ func UntarToDir(r io.Reader, dir string) error { if err != nil { return err } - if _, err := io.Copy(f, tr); err != nil { // nolint[gosec] + lr := &limitReader{r: tr, n: maxFileSize} // gosec G110 + if _, err := io.Copy(f, lr); err != nil { return err } if runtime.GOOS != "windows" { diff --git a/test/context/settings.go b/test/context/settings.go index 56854a9b..57a0fbd4 100644 --- a/test/context/settings.go +++ b/test/context/settings.go @@ -43,8 +43,8 @@ func newFakeSettings() *fakeSettings { } // We should use nonstandard ports to not conflict with bridge. - s.SetInt(settings.IMAPPortKey, 21100+rand.Intn(100)) - s.SetInt(settings.SMTPPortKey, 21200+rand.Intn(100)) + s.SetInt(settings.IMAPPortKey, 21100+rand.Intn(100)) //noling[gosec] G404 It is OK to use weak random number generator here + s.SetInt(settings.SMTPPortKey, 21200+rand.Intn(100)) //noling[gosec] G404 It is OK to use weak random number generator here return s }