From 38ccb1928fab1d78e2fc7385ce13c80cf56e4045 Mon Sep 17 00:00:00 2001 From: Fred Date: Sun, 25 Aug 2024 13:34:21 +0100 Subject: [PATCH 1/4] fix overflow integer conversion lint warning from gosec --- filesearch/filesearch_test.go | 2 +- lock/lock.go | 6 +++--- lock/lock_test.go | 10 +++++----- shell/command.go | 4 ++-- shell/command_test.go | 4 ++-- shell_command.go | 2 +- term/term.go | 10 +++++++--- util/templates/functions_test.go | 2 +- wrapper.go | 2 +- 9 files changed, 23 insertions(+), 19 deletions(-) diff --git a/filesearch/filesearch_test.go b/filesearch/filesearch_test.go index 383ce830..54edf7a9 100644 --- a/filesearch/filesearch_test.go +++ b/filesearch/filesearch_test.go @@ -314,7 +314,7 @@ func TestShellExpand(t *testing.T) { func TestFindConfigurationIncludes(t *testing.T) { t.Parallel() - testID := fmt.Sprintf("%d", uint32(time.Now().UnixNano())) + testID := fmt.Sprintf("%x", time.Now().UnixNano()) tempDir := os.TempDir() files := []string{ filepath.Join(tempDir, "base."+testID+".conf"), diff --git a/lock/lock.go b/lock/lock.go index d3cd514d..fa1dd2a2 100644 --- a/lock/lock.go +++ b/lock/lock.go @@ -13,7 +13,7 @@ import ( ) // SetPID is a callback that writes the PID in the lockfile -type SetPID func(pid int) +type SetPID func(pid int32) // Lock prevents code to run at the same time by using a lockfile type Lock struct { @@ -83,7 +83,7 @@ func (l *Lock) Who() (string, error) { // SetPID writes down the PID in the lock file. // You can run the method as many times as you want when the PID changes -func (l *Lock) SetPID(pid int) { +func (l *Lock) SetPID(pid int32) { if !l.locked { return } @@ -109,7 +109,7 @@ func (l *Lock) LastPID() (int32, error) { if contents[i] != "" { pid, err := strconv.ParseInt(contents[i], 10, 32) if err == nil { - return int32(pid), nil + return int32(pid), nil //nolint:gosec } } } diff --git a/lock/lock_test.go b/lock/lock_test.go index 1bc92003..a4ad94c3 100644 --- a/lock/lock_test.go +++ b/lock/lock_test.go @@ -130,16 +130,16 @@ func TestSetMorePID(t *testing.T) { func TestProcessPID(t *testing.T) { t.Parallel() - childPID := 0 + var childPID int32 buffer := &bytes.Buffer{} // use the lock helper binary (we only need to wait for some time, we don't need the locking part) cmd := shell.NewCommand(helperBinary, []string{"-wait", "200", "-lock", filepath.Join(t.TempDir(), t.Name())}) cmd.Stdout = buffer // SetPID method is called right after we forked and have a PID available - cmd.SetPID = func(pid int) { + cmd.SetPID = func(pid int32) { childPID = pid - running, err := process.PidExists(int32(childPID)) + running, err := process.PidExists(childPID) assert.NoError(t, err) assert.True(t, running) } @@ -147,7 +147,7 @@ func TestProcessPID(t *testing.T) { require.NoError(t, err) // at that point, the child process should be finished - running, err := process.PidExists(int32(childPID)) + running, err := process.PidExists(childPID) assert.NoError(t, err) assert.False(t, running) } @@ -220,7 +220,7 @@ func TestForceLockWithRunningPID(t *testing.T) { // user the lock helper binary (we only need to wait for some time, we don't need the locking part) cmd := shell.NewCommand(helperBinary, []string{"-wait", "100", "-lock", filepath.Join(t.TempDir(), t.Name())}) - cmd.SetPID = func(pid int) { + cmd.SetPID = func(pid int32) { lock.SetPID(pid) // make sure we cannot break the lock right now other := NewLock(tempfile) diff --git a/shell/command.go b/shell/command.go index a34c6e75..deac69a9 100644 --- a/shell/command.go +++ b/shell/command.go @@ -27,7 +27,7 @@ const ( ) // SetPID is a callback to send the PID of the current child process -type SetPID func(pid int) +type SetPID func(pid int32) // ScanOutput is a callback to scan the default output of the command // The implementation is expected to send everything read from the reader back to the writer @@ -124,7 +124,7 @@ func (c *Command) Run() (monitor.Summary, string, error) { } if c.SetPID != nil { // send the PID back (to write down in a lockfile) - c.SetPID(cmd.Process.Pid) + c.SetPID(int32(cmd.Process.Pid)) //nolint:gosec } // setup the OS signalling if we need it (typically used for unixes but not windows) if c.sigChan != nil { diff --git a/shell/command_test.go b/shell/command_test.go index a1f66729..09048900 100644 --- a/shell/command_test.go +++ b/shell/command_test.go @@ -399,7 +399,7 @@ func TestSetPIDCallback(t *testing.T) { buffer := &bytes.Buffer{} cmd := NewCommand("echo", []string{t.Name()}) cmd.Stdout = buffer - cmd.SetPID = func(pid int) { + cmd.SetPID = func(pid int32) { called++ } _, _, err := cmd.Run() @@ -420,7 +420,7 @@ func TestSetPIDCallbackWithSignalling(t *testing.T) { cmd := NewSignalledCommand("echo", []string{t.Name()}, c) cmd.Stdout = buffer - cmd.SetPID = func(pid int) { + cmd.SetPID = func(pid int32) { called++ } _, _, err := cmd.Run() diff --git a/shell_command.go b/shell_command.go index 7ab6adf3..f576637b 100644 --- a/shell_command.go +++ b/shell_command.go @@ -30,7 +30,7 @@ type shellCommandDefinition struct { } // newShellCommand creates a new shell command definition -func newShellCommand(command string, args, env, shell []string, dryRun bool, sigChan chan os.Signal, setPID func(pid int)) shellCommandDefinition { +func newShellCommand(command string, args, env, shell []string, dryRun bool, sigChan chan os.Signal, setPID func(pid int32)) shellCommandDefinition { if env == nil { env = make([]string, 0) } diff --git a/term/term.go b/term/term.go index b1c47ff7..2ea2457e 100644 --- a/term/term.go +++ b/term/term.go @@ -58,7 +58,7 @@ func AskYesNo(reader io.Reader, message string, defaultAnswer bool) bool { // ReadPassword reads a password without echoing it to the terminal. func ReadPassword() (string, error) { - stdin := int(os.Stdin.Fd()) + stdin := fdToInt(os.Stdin.Fd()) if !term.IsTerminal(stdin) { return ReadLine() } @@ -82,13 +82,13 @@ func ReadLine() (string, error) { // OsStdoutIsTerminal returns true as os.Stdout is a terminal session func OsStdoutIsTerminal() bool { - fd := int(os.Stdout.Fd()) + fd := fdToInt(os.Stdout.Fd()) return term.IsTerminal(fd) } // OsStdoutIsTerminal returns true as os.Stdout is a terminal session func OsStdoutTerminalSize() (width, height int) { - fd := int(os.Stdout.Fd()) + fd := fdToInt(os.Stdout.Fd()) var err error width, height, err = term.GetSize(fd) if err != nil { @@ -97,6 +97,10 @@ func OsStdoutTerminalSize() (width, height int) { return } +func fdToInt(fd uintptr) int { + return int(fd) //nolint:gosec +} + type LockedWriter struct { writer io.Writer mutex *sync.Mutex diff --git a/util/templates/functions_test.go b/util/templates/functions_test.go index 5170fad0..85025ef7 100644 --- a/util/templates/functions_test.go +++ b/util/templates/functions_test.go @@ -90,7 +90,7 @@ func TestTemplateFuncs(t *testing.T) { }) t.Run("envFileFunc", func(t *testing.T) { - profileKey := fmt.Sprintf("prof-%d", int(rand.Uint64())) + profileKey := fmt.Sprintf("prof-%x", rand.Uint64()) expectedFile := TempFile(fmt.Sprintf("%s.env", profileKey)) var received []string diff --git a/wrapper.go b/wrapper.go index ff062f70..2a94e389 100644 --- a/wrapper.go +++ b/wrapper.go @@ -37,7 +37,7 @@ type resticWrapper struct { command string moreArgs []string sigChan chan os.Signal - setPID func(pid int) + setPID func(pid int32) stdin io.ReadCloser progress []monitor.Receiver sender *hook.Sender From 2632613f0af0e6ae6c51a781c32f5c46e15a1b32 Mon Sep 17 00:00:00 2001 From: Fred Date: Sun, 25 Aug 2024 14:37:27 +0100 Subject: [PATCH 2/4] fix integer conversion for linux and windows builds --- Makefile | 10 ++++++++++ priority/ioprio_linux.go | 6 +++--- schtasks/taskscheduler.go | 22 +++++++++++----------- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index dfb02581..297b1d01 100644 --- a/Makefile +++ b/Makefile @@ -278,10 +278,12 @@ generate-config-reference: build LAYOUT_UPLINK="[go to top](#reference)" \ $(abspath $(BINARY)) generate --config-reference --to $(CONFIG_REFERENCE_DIR) +.PHONY: documentation documentation: generate-jsonschema generate-config-reference @echo "[*] $@" cd docs && hugo --minify +.PHONY: syslog-ng syslog-ng: @echo "[*] $@" docker run -d \ @@ -300,6 +302,14 @@ checkdoc: @echo "[*] $@" $(GOCMD) run ./config/checkdoc -r docs/content +.PHONY: checklinks checklinks: @echo "[*] $@" muffet -b 8192 --exclude="(linux.die.net|stackoverflow.com)" http://localhost:1313/resticprofile/ + +.PHONY: lint +lint: + @echo "[*] $@" + GOOS=darwin golangci-lint run + GOOS=linux golangci-lint run + GOOS=windows golangci-lint run diff --git a/priority/ioprio_linux.go b/priority/ioprio_linux.go index cfcb603b..af992321 100644 --- a/priority/ioprio_linux.go +++ b/priority/ioprio_linux.go @@ -71,9 +71,9 @@ func getIOPrio(who IOPrioWho) (IOPrioClass, int, error) { if errno != 0 { return 0, 0, errnoToError(errno) } - class := r1 >> IOPrioClassShift - value := r1 & IOPrioMask - return IOPrioClass(class), int(value), nil + class := IOPrioClass(r1 >> IOPrioClassShift) //nolint:gosec + value := int(r1 & IOPrioMask) //nolint:gosec + return class, value, nil } func setIOPrio(who IOPrioWho, class IOPrioClass, value int) error { diff --git a/schtasks/taskscheduler.go b/schtasks/taskscheduler.go index e02a3baf..feab984c 100644 --- a/schtasks/taskscheduler.go +++ b/schtasks/taskscheduler.go @@ -589,18 +589,18 @@ func compileDifferences(recurrences []time.Time) ([]time.Duration, []time.Durati return differences, compactDifferences } -func convertWeekdaysToBitmap(weekdays []int) int { +func convertWeekdaysToBitmap(weekdays []int) uint16 { if len(weekdays) == 0 { return 0 } - bitmap := 0 + var bitmap uint16 for _, weekday := range weekdays { bitmap |= getWeekdayBit(weekday) } return bitmap } -func getWeekdayBit(weekday int) int { +func getWeekdayBit(weekday int) uint16 { switch weekday { case 0: return 1 @@ -623,32 +623,32 @@ func getWeekdayBit(weekday int) int { return 0 } -func convertMonthsToBitmap(months []int) int { +func convertMonthsToBitmap(months []int) uint16 { if months == nil { return 0 } if len(months) == 0 { // all values - return int(math.Exp2(12)) - 1 + return uint16(math.Exp2(12)) - 1 } - bitmap := 0 + var bitmap uint16 for _, month := range months { - bitmap |= int(math.Exp2(float64(month - 1))) + bitmap |= uint16(math.Exp2(float64(month - 1))) } return bitmap } -func convertDaysToBitmap(days []int) int { +func convertDaysToBitmap(days []int) uint32 { if days == nil { return 0 } if len(days) == 0 { // every day - return int(math.Exp2(31)) - 1 + return uint32(math.Exp2(31)) - 1 } - bitmap := 0 + var bitmap uint32 for _, day := range days { - bitmap |= int(math.Exp2(float64(day - 1))) + bitmap |= uint32(math.Exp2(float64(day - 1))) } return bitmap } From 084d5b8cfe70315aad81013ae3f5ef9cb585a2a0 Mon Sep 17 00:00:00 2001 From: Fred Date: Sun, 25 Aug 2024 14:51:07 +0100 Subject: [PATCH 3/4] fix type in tests --- schtasks/taskscheduler_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/schtasks/taskscheduler_test.go b/schtasks/taskscheduler_test.go index 7778ddba..a93fe25c 100644 --- a/schtasks/taskscheduler_test.go +++ b/schtasks/taskscheduler_test.go @@ -22,7 +22,7 @@ import ( func TestConversionWeekdaysToBitmap(t *testing.T) { testData := []struct { weekdays []int - bitmap int + bitmap uint16 }{ {nil, 0}, {[]int{}, 0}, @@ -111,7 +111,7 @@ func TestTaskSchedulerConversion(t *testing.T) { // 3rd task will be a weekly recurring weeklyEvent, ok := task.Triggers[2].(taskmaster.WeeklyTrigger) require.True(t, ok) - assert.Equal(t, getWeekdayBit(int(time.Saturday))+getWeekdayBit(int(time.Sunday)), int(weeklyEvent.DaysOfWeek)) + assert.Equal(t, getWeekdayBit(int(time.Saturday))+getWeekdayBit(int(time.Sunday)), uint16(weeklyEvent.DaysOfWeek)) // 4th task will be a monthly recurring monthlyEvent, ok := task.Triggers[3].(taskmaster.MonthlyTrigger) From 9af9f3e02d3a9196313e750e86c1141e6fbd5719 Mon Sep 17 00:00:00 2001 From: Fred Date: Sun, 25 Aug 2024 15:35:44 +0100 Subject: [PATCH 4/4] use binary shift to compute power of 2 --- Makefile | 9 +++++++ schedule/tree_darwin.go | 2 +- schedule/tree_darwin_test.go | 1 - schtasks/taskscheduler.go | 13 ++++++---- schtasks/taskscheduler_test.go | 43 ++++++++++++++++++++++++++++++++++ win/other.go | 2 +- win/windows.go | 1 - 7 files changed, 62 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 297b1d01..d5cec0af 100644 --- a/Makefile +++ b/Makefile @@ -313,3 +313,12 @@ lint: GOOS=darwin golangci-lint run GOOS=linux golangci-lint run GOOS=windows golangci-lint run + +.PHONY: fix +fix: + @echo "[*] $@" + $(GOCMD) mod tidy + $(GOCMD) fix ./... + GOOS=darwin golangci-lint run --fix + GOOS=linux golangci-lint run --fix + GOOS=windows golangci-lint run --fix diff --git a/schedule/tree_darwin.go b/schedule/tree_darwin.go index 9aa96636..872a2d9d 100644 --- a/schedule/tree_darwin.go +++ b/schedule/tree_darwin.go @@ -1,4 +1,4 @@ -//+build darwin +//go:build darwin package schedule diff --git a/schedule/tree_darwin_test.go b/schedule/tree_darwin_test.go index a9a827e3..25d6f597 100644 --- a/schedule/tree_darwin_test.go +++ b/schedule/tree_darwin_test.go @@ -1,5 +1,4 @@ //go:build darwin -// +build darwin package schedule diff --git a/schtasks/taskscheduler.go b/schtasks/taskscheduler.go index feab984c..71415133 100644 --- a/schtasks/taskscheduler.go +++ b/schtasks/taskscheduler.go @@ -5,7 +5,6 @@ package schtasks import ( "errors" "fmt" - "math" "os/user" "strings" "text/tabwriter" @@ -629,11 +628,13 @@ func convertMonthsToBitmap(months []int) uint16 { } if len(months) == 0 { // all values - return uint16(math.Exp2(12)) - 1 + return (1 << 12) - 1 } var bitmap uint16 for _, month := range months { - bitmap |= uint16(math.Exp2(float64(month - 1))) + if month > 0 && month <= 12 { + bitmap |= 1 << (month - 1) + } } return bitmap } @@ -644,11 +645,13 @@ func convertDaysToBitmap(days []int) uint32 { } if len(days) == 0 { // every day - return uint32(math.Exp2(31)) - 1 + return (1 << 31) - 1 } var bitmap uint32 for _, day := range days { - bitmap |= uint32(math.Exp2(float64(day - 1))) + if day > 0 && day <= 31 { + bitmap |= 1 << (day - 1) + } } return bitmap } diff --git a/schtasks/taskscheduler_test.go b/schtasks/taskscheduler_test.go index a93fe25c..65857ced 100644 --- a/schtasks/taskscheduler_test.go +++ b/schtasks/taskscheduler_test.go @@ -4,6 +4,7 @@ package schtasks import ( "bytes" + "math" "os/exec" "regexp" "strconv" @@ -40,6 +41,48 @@ func TestConversionWeekdaysToBitmap(t *testing.T) { } } +func TestConversionMonthsToBitmap(t *testing.T) { + testData := []struct { + months []int + bitmap uint16 + }{ + {nil, 0}, + {[]int{}, 4095}, // every month + {[]int{0}, 0}, + {[]int{1}, 1}, + {[]int{2}, 2}, + {[]int{7}, 64}, + {[]int{1, 2, 3, 4, 5, 6, 7}, 127}, + {[]int{0, 1, 2, 3, 4, 5, 6, 7}, 127}, + {[]int{1, 2, 3, 4, 5, 6}, 63}, + } + + for _, testItem := range testData { + assert.Equal(t, testItem.bitmap, convertMonthsToBitmap(testItem.months)) + } +} + +func TestConversionDaysToBitmap(t *testing.T) { + testData := []struct { + days []int + bitmap uint32 + }{ + {nil, 0}, + {[]int{}, math.MaxInt32}, // every day + {[]int{0}, 0}, + {[]int{1}, 1}, + {[]int{2}, 2}, + {[]int{7}, 64}, + {[]int{1, 2, 3, 4, 5, 6, 7}, 127}, + {[]int{0, 1, 2, 3, 4, 5, 6, 7}, 127}, + {[]int{1, 2, 3, 4, 5, 6}, 63}, + } + + for _, testItem := range testData { + assert.Equal(t, testItem.bitmap, convertDaysToBitmap(testItem.days)) + } +} + func TestCompileDifferences(t *testing.T) { testData := []struct { input string diff --git a/win/other.go b/win/other.go index 0890c9fd..7f733e3b 100644 --- a/win/other.go +++ b/win/other.go @@ -1,4 +1,4 @@ -// +build !windows +//go:build !windows package win diff --git a/win/windows.go b/win/windows.go index 234b2d7e..078ea485 100644 --- a/win/windows.go +++ b/win/windows.go @@ -1,5 +1,4 @@ //go:build windows -// +build windows package win