Skip to content

Commit 6d26c72

Browse files
Add several linters to CI and fix found issues (#542)
* fix a bunch of error strings * add linters to makefile * import sort * renamed .template/ files to .tmpl to prevent goimports from failing to parse * fix fatcontext errors * fix prealloc lints * ineffassign lints * unused, not touching the lib/ dir * fix perfsprint errors * fixed or silenced static check errors * last prealloc * fix govet errors * errcheck * don't lint lib/ dir * lint * add golangci-yml lint and imports check to lint CI * bump for tests * don't error when hitting EOF in copy in http * fix but in err handling in utility * fix error handling in ReadAvailableWithOptions * fix mssql error where we abort a scan if we can't get the tlsconn, we should proceed because we can still extract version and other info without a TLS conn * pr review
1 parent fd435bd commit 6d26c72

File tree

111 files changed

+761
-648
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

111 files changed

+761
-648
lines changed

.github/workflows/linter.yml

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,34 @@ jobs:
5050
uses: actions/upload-artifact@v4
5151
with:
5252
name: formatted-files
53-
path: /tmp/gofmt
53+
path: /tmp/gofmt
54+
goimports-and-golangci-lint:
55+
runs-on: ubuntu-latest
56+
steps:
57+
- name: Checkout
58+
uses: actions/checkout@v4
59+
- name: Setup Go
60+
uses: actions/setup-go@v5
61+
with:
62+
go-version: "1.23"
63+
- name: Other lint
64+
run: |
65+
go install golang.org/x/tools/cmd/goimports@latest
66+
output=$(goimports -d -local "github.com/zmap/zdns" ./)
67+
if [ -n "$output" ]; then
68+
echo "goimports found issues:"
69+
echo "$output"
70+
exit 1
71+
else
72+
echo "No issues found by goimports."
73+
fi
74+
output=$(gofmt -d .)
75+
if [ -n "$output" ]; then
76+
echo "gofmt found issues:"
77+
echo "$output"
78+
exit 1
79+
else
80+
echo "No issues found by gofmt."
81+
fi
82+
- name: golangci-lint
83+
uses: golangci/golangci-lint-action@v8.0.0

.golangci.yml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# This code is licensed under the terms of the MIT license https://opensource.org/license/mit
2+
# Copyright (c) 2021 Marat Reymers
3+
4+
version: "2"
5+
linters:
6+
default: none
7+
enable:
8+
- errcheck
9+
- fatcontext
10+
- govet
11+
- ineffassign
12+
- perfsprint
13+
- prealloc
14+
- staticcheck
15+
- unused
16+
settings:
17+
errcheck:
18+
check-type-assertions: true
19+
govet:
20+
disable:
21+
- fieldalignment
22+
enable-all: true
23+
settings:
24+
shadow:
25+
strict: false
26+
exclusions:
27+
generated: lax
28+
presets:
29+
- comments
30+
- common-false-positives
31+
- legacy
32+
- std-error-handling
33+
rules:
34+
- linters:
35+
- errcheck
36+
path: _test\.go
37+
paths:
38+
- third_party$
39+
- builtin$
40+
- examples$
41+
- lib/*
42+
issues:
43+
max-issues-per-linter: 50
44+
formatters:
45+
exclusions:
46+
generated: lax
47+
paths:
48+
- third_party$
49+
- builtin$
50+
- examples$

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ test:
2020

2121
lint:
2222
gofmt -s -w $(shell find . -type f -name '*.go'| grep -v "/.template/")
23+
goimports -w -local "github.com/zmap/zgrab2" ./
24+
golangci-lint run
2325
black .
2426

2527
zgrab2: $(GO_FILES)

bin/bin.go

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import (
44
"encoding/json"
55
"os"
66
"runtime/pprof"
7+
"strconv"
78
"sync"
89
"time"
910

10-
"fmt"
1111
"runtime"
1212
"strings"
1313

@@ -35,9 +35,9 @@ func getCPUProfileFile() string {
3535
// YYYYMMDDhhmmss, and {NANOS} as the decimal nanosecond offset.
3636
func getFormattedFile(formatString string, when time.Time) string {
3737
timestamp := when.Format("20060102150405")
38-
nanos := fmt.Sprintf("%d", when.Nanosecond())
39-
ret := strings.Replace(formatString, "{TIMESTAMP}", timestamp, -1)
40-
ret = strings.Replace(ret, "{NANOS}", nanos, -1)
38+
nanos := strconv.Itoa(when.Nanosecond())
39+
ret := strings.ReplaceAll(formatString, "{TIMESTAMP}", timestamp)
40+
ret = strings.ReplaceAll(ret, "{NANOS}", nanos)
4141
return ret
4242
}
4343

@@ -128,16 +128,24 @@ func ZGrab2Main() {
128128
log.Fatalf("error parsing flags")
129129
}
130130
for i, fl := range flagsReturned {
131-
f, _ := fl.(zgrab2.ScanFlags)
131+
f, ok := fl.(zgrab2.ScanFlags)
132+
if !ok {
133+
log.Fatalf("error parsing flags as ScanFlags")
134+
}
132135
mod := zgrab2.GetModule(modTypes[i])
133136
s := mod.NewScanner()
134-
s.Init(f)
137+
138+
if err = s.Init(f); err != nil {
139+
log.Panicf("could not initialize multiple scanner: %v", err)
140+
}
135141
zgrab2.RegisterScan(s.GetName(), s)
136142
}
137143
} else {
138144
mod := zgrab2.GetModule(moduleType)
139145
s := mod.NewScanner()
140-
s.Init(flag)
146+
if err = s.Init(flag); err != nil {
147+
log.Panicf("could not initialize scanner %s: %v", moduleType, err)
148+
}
141149
zgrab2.RegisterScan(moduleType, s)
142150
}
143151
wg := sync.WaitGroup{}

config.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ type Config struct {
4040
inputTargets InputTargetsFunc
4141
outputResults OutputResultsFunc
4242
customDNSNameservers []string // will be non-empty if user specified custom DNS, we'll check these are reachable before populating
43-
localAddr *net.TCPAddr
4443
localAddrs []net.IP // will be non-empty if user specified local addresses
4544
localPorts []uint16 // will be non-empty if user specified local ports
4645
useIPv4 bool // true if zgrab should use IPv4 addresses after resolving domains
@@ -102,7 +101,7 @@ func validateFrameworkConfiguration() {
102101
} else if len(config.MetaFileName) > 0 {
103102
var err error
104103
if config.metaFile, err = os.Create(config.MetaFileName); err != nil {
105-
log.Fatal(fmt.Errorf("error creating meta file: %s", err))
104+
log.Fatal(fmt.Errorf("error creating meta file: %w", err))
106105
}
107106
}
108107

@@ -111,7 +110,7 @@ func validateFrameworkConfiguration() {
111110
} else if len(config.StatusUpdatesFileName) > 0 {
112111
var err error
113112
if config.statusUpdatesFile, err = os.Create(config.StatusUpdatesFileName); err != nil {
114-
log.Fatal(fmt.Errorf("error creating status updates file: %v", err))
113+
log.Fatal(fmt.Errorf("error creating status updates file: %w", err))
115114
}
116115
}
117116

@@ -295,11 +294,11 @@ func extractPorts(portString string) ([]uint16, error) {
295294
}
296295
startPort, err := parsePortString(parts[0])
297296
if err != nil {
298-
return nil, fmt.Errorf("invalid start port %s of port range: %v", parts[0], err)
297+
return nil, fmt.Errorf("invalid start port %s of port range: %w", parts[0], err)
299298
}
300299
endPort, err := parsePortString(parts[1])
301300
if err != nil {
302-
return nil, fmt.Errorf("invalid end port %s of port range: %v", parts[1], err)
301+
return nil, fmt.Errorf("invalid end port %s of port range: %w", parts[1], err)
303302
}
304303
if startPort >= endPort {
305304
return nil, fmt.Errorf("start port %d must be less than end port %d", startPort, endPort)
@@ -312,7 +311,7 @@ func extractPorts(portString string) ([]uint16, error) {
312311
// single port
313312
port, err := parsePortString(portStr)
314313
if err != nil {
315-
return nil, fmt.Errorf("invalid port %s: %v", portStr, err)
314+
return nil, fmt.Errorf("invalid port %s: %w", portStr, err)
316315
}
317316
portMap[port] = struct{}{}
318317
}

conn.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func (c *TimeoutConnection) SaturateTimeoutsToReadAndWriteTimeouts() {
7070
// Get the minimum of the context deadline and the timeout
7171
minDeadline := int64(math.MaxInt64)
7272
if ctxDeadline, ok := c.ctx.Deadline(); ok {
73-
minDeadline = int64(ctxDeadline.Sub(time.Now()))
73+
minDeadline = int64(time.Until(ctxDeadline))
7474
}
7575
if c.SessionTimeout > 0 {
7676
minDeadline = min(minDeadline, int64(c.SessionTimeout))
@@ -93,7 +93,7 @@ func (c *TimeoutConnection) SaturateTimeoutsToReadAndWriteTimeouts() {
9393

9494
// TimeoutConnection.Read calls Read() on the underlying connection, using any configured deadlines
9595
func (c *TimeoutConnection) Read(b []byte) (n int, err error) {
96-
if err := c.checkContext(); err != nil {
96+
if err = c.checkContext(); err != nil {
9797
return 0, err
9898
}
9999
origSize := len(b)
@@ -125,7 +125,7 @@ func (c *TimeoutConnection) Read(b []byte) (n int, err error) {
125125

126126
// TimeoutConnection.Write calls Write() on the underlying connection, using any configured deadlines.
127127
func (c *TimeoutConnection) Write(b []byte) (n int, err error) {
128-
if err := c.checkContext(); err != nil {
128+
if err = c.checkContext(); err != nil {
129129
return 0, err
130130
}
131131
c.SaturateTimeoutsToReadAndWriteTimeouts()
@@ -144,7 +144,7 @@ func (c *TimeoutConnection) SetReadDeadline(deadline time.Time) error {
144144
return err
145145
}
146146
if !deadline.IsZero() {
147-
c.ReadTimeout = deadline.Sub(time.Now())
147+
c.ReadTimeout = time.Until(deadline)
148148
}
149149
return nil
150150
}
@@ -156,7 +156,7 @@ func (c *TimeoutConnection) SetWriteDeadline(deadline time.Time) error {
156156
return err
157157
}
158158
if !deadline.IsZero() {
159-
c.WriteTimeout = deadline.Sub(time.Now())
159+
c.WriteTimeout = time.Until(deadline)
160160
}
161161
return nil
162162
}
@@ -291,7 +291,7 @@ func (d *Dialer) SetDefaults() *Dialer {
291291
d.Dialer = &net.Dialer{}
292292
// this may be a single IP address or a comma-separated list of IP addresses
293293
ns := config.customDNSNameservers[rand.Intn(len(config.customDNSNameservers))]
294-
d.Dialer.Resolver = &net.Resolver{
294+
d.Resolver = &net.Resolver{
295295
PreferGo: true,
296296
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
297297
return d.Dialer.DialContext(ctx, network, ns)

conn_bytelimit_test.go

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,20 @@ import (
1111
)
1212

1313
// Start a local echo server on port.
14-
func runEchoServer(t *testing.T, port int) {
14+
func runEchoServer(t *testing.T, port int) <-chan error {
1515
endpoint := fmt.Sprintf("127.0.0.1:%d", port)
1616
listener, err := net.Listen("tcp", endpoint)
1717
if err != nil {
1818
t.Fatal(err)
1919
}
20+
errChan := make(chan error)
2021
go func() {
22+
defer close(errChan)
2123
defer listener.Close()
2224
sock, err := listener.Accept()
2325
if err != nil {
24-
t.Fatal(err)
26+
errChan <- err
27+
return
2528
}
2629
defer sock.Close()
2730

@@ -30,12 +33,12 @@ func runEchoServer(t *testing.T, port int) {
3033
n, err := sock.Read(buf)
3134
if err != nil {
3235
if err != io.EOF && !strings.Contains(err.Error(), "connection reset") {
33-
t.Fatal(err)
36+
errChan <- err
3437
}
3538
return
3639
}
3740
sock.SetWriteDeadline(time.Now().Add(time.Millisecond * 250))
38-
n, err = sock.Write(buf[0:n])
41+
_, err = sock.Write(buf[0:n])
3942
if err != nil {
4043
if err != io.EOF && !strings.Contains(err.Error(), "connection reset") && !strings.Contains(err.Error(), "broken pipe") {
4144
t.Logf("Unexpected error writing to client: %v", err)
@@ -44,6 +47,7 @@ func runEchoServer(t *testing.T, port int) {
4447
}
4548
}
4649
}()
50+
return errChan
4751
}
4852

4953
// Interface for getting a TimeoutConnection; we want to test both the dialer and the direct Dial functions.
@@ -185,7 +189,7 @@ func getTestBuffer(size int) []byte {
185189

186190
// Check that buf is of the type returned by getTestBuffer.
187191
func checkTestBuffer(buf []byte) bool {
188-
if buf == nil || len(buf) == 0 {
192+
if len(buf) == 0 {
189193
return false
190194
}
191195
for i, v := range buf {
@@ -344,7 +348,7 @@ func runBytesReadLimitTrial(t *testing.T, connector timeoutConnector, idx int, m
344348
ctx, cancel := context.WithCancel(context.Background())
345349
defer cancel()
346350
port := 0x1234 + idx
347-
runEchoServer(t, port)
351+
errChan := runEchoServer(t, port)
348352
conn, err := connector.connect(ctx, t, port, idx)
349353
if err != nil {
350354
t.Fatalf("Error dialing: %v", err)
@@ -360,7 +364,19 @@ func runBytesReadLimitTrial(t *testing.T, connector timeoutConnector, idx int, m
360364
}
361365
}()
362366
defer conn.Close()
363-
return method(cfg, t, conn, idx)
367+
err = method(cfg, t, conn, idx)
368+
if err != nil {
369+
return err
370+
}
371+
// Check if the server has any errors
372+
select {
373+
case err := <-errChan:
374+
if err != nil {
375+
t.Fatalf("Error in server: %v", err)
376+
}
377+
default:
378+
}
379+
return nil
364380
}
365381

366382
// Run a full set of trials on the connector -- ten with a single send, and ten with multiple sends.

conn_timeout_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ func (cfg *connTimeoutTestConfig) runServer(t *testing.T, stopServer <-chan stru
133133
}
134134
defer sock.Close()
135135
time.Sleep(cfg.serverWriteDelay)
136-
if err := _write(sock, cfg.serverToClientPayload); err != nil {
136+
if err = _write(sock, cfg.serverToClientPayload); err != nil {
137137
errorChan <- serverError(clientTestStepRead, err)
138138
return
139139
}
@@ -152,7 +152,6 @@ func (cfg *connTimeoutTestConfig) runServer(t *testing.T, stopServer <-chan stru
152152
t.Errorf("%s: clientToServerPayload mismatch", cfg.name)
153153
}
154154
<-stopServer // wait for client to indicate server can exit
155-
return
156155
}()
157156
return errorChan
158157
}

fake_resolver.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ import (
44
"context"
55
"errors"
66
"fmt"
7-
"golang.org/x/net/dns/dnsmessage"
87
"net"
98
"time"
9+
10+
"golang.org/x/net/dns/dnsmessage"
1011
)
1112

1213
// Fake DNS Resolver, to force a DNS lookup to return a pinned address
@@ -19,7 +20,7 @@ import (
1920
func NewFakeResolver(ipstr string) (*net.Resolver, error) {
2021
ip := net.ParseIP(ipstr)
2122
if len(ip) < 4 {
22-
return nil, fmt.Errorf("Fake resolver can't use non-IP '%s'", ipstr)
23+
return nil, fmt.Errorf("fake resolver can't use non-IP '%s'", ipstr)
2324
}
2425
fDNS := FakeDNSServer{
2526
IP: ip,
@@ -86,7 +87,7 @@ func (f *FakeDNSServer) fakeDNS(s string, dmsg dnsmessage.Message) (r dnsmessage
8687
},
8788
}
8889
default:
89-
r.Header.RCode = dnsmessage.RCodeNameError
90+
r.RCode = dnsmessage.RCodeNameError
9091
}
9192

9293
return r, nil
@@ -124,7 +125,7 @@ func (fc *fakeDNSConn) Read(b []byte) (int, error) {
124125
bb := make([]byte, 2, 514)
125126
bb, err = resp.AppendPack(bb)
126127
if err != nil {
127-
return 0, fmt.Errorf("cannot marshal DNS message: %v", err)
128+
return 0, fmt.Errorf("cannot marshal DNS message: %w", err)
128129
}
129130

130131
bb = bb[2:]

0 commit comments

Comments
 (0)