diff --git a/Makefile b/Makefile index 2f758ea022b162d48ec386a5aa9f9583f1658d71..883d600b186d788a0dc5fc39fb8c80cc074914cc 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ get-build-deps: getdeps: @mkdir -p ${GOPATH}/bin @which golangci-lint 1>/dev/null || (echo "Installing golangci-lint" && curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GOPATH)/bin v1.27.0) - @which ruleguard 1>/dev/null || (echo "Installing ruleguard" && GO111MODULE=off go get github.com/quasilyte/go-ruleguard/...) + @which ruleguard 1>/dev/null || (echo "Installing ruleguard" && go get github.com/quasilyte/go-ruleguard/cmd/ruleguard@v0.2.1) tools/bin/revive: tools/check/go.mod cd tools/check; \ @@ -82,7 +82,7 @@ else @${GOPATH}/bin/ruleguard -rules ruleguard.rules.go ./tests/go/... endif -verifiers: getdeps cppcheck fmt static-check +verifiers: getdeps cppcheck fmt static-check ruleguard # Builds various components locally. build-go: build-cpp get-rocksdb diff --git a/build/docker/env/cpu/ubuntu18.04/Dockerfile b/build/docker/env/cpu/ubuntu18.04/Dockerfile index 2a9a42e9bed338ae835c6e22ae3cb5a93afbb002..2815f2000cfc909eed9fbe2f85523d1e3a74379e 100644 --- a/build/docker/env/cpu/ubuntu18.04/Dockerfile +++ b/build/docker/env/cpu/ubuntu18.04/Dockerfile @@ -40,7 +40,7 @@ ENV PATH $GOPATH/bin:$GOROOT/bin:$PATH RUN mkdir -p /usr/local/go && wget -qO- "https://golang.org/dl/go1.15.2.linux-amd64.tar.gz" | tar --strip-components=1 -xz -C /usr/local/go && \ mkdir -p "$GOPATH/src" "$GOPATH/bin" && \ curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b ${GOPATH}/bin v1.27.0 && \ - export GO111MODULE=off && go get github.com/quasilyte/go-ruleguard/... && \ + export GO111MODULE=on && go get github.com/quasilyte/go-ruleguard/cmd/ruleguard@v0.2.1 && \ chmod -R 777 "$GOPATH" && chmod -R a+w $(go env GOTOOLDIR) RUN apt-get update && apt-get install -y --no-install-recommends \ diff --git a/internal/proxy/task.go b/internal/proxy/task.go index bd2251a2d851b729548c1f92376fd4779730298c..ba7a853c20b8e0b09bfed3d58e81fe16abeb83b1 100644 --- a/internal/proxy/task.go +++ b/internal/proxy/task.go @@ -572,7 +572,7 @@ func (qt *QueryTask) PostExecute() error { continue } distance := hits[q][i].Scores[loc] - if distance > maxDistance || (distance == maxDistance && choice != q) { + if distance > maxDistance || (math.Abs(float64(distance-maxDistance)) < math.SmallestNonzeroFloat32 && choice != q) { choice = q maxDistance = distance valid = true diff --git a/ruleguard.rules.go b/ruleguard.rules.go index 3ed15287e9ed00f748d5a5057ef49ffe6fb687bf..cf566e2f52e3fb02c107cbc1b76c70d2dc24a616 100644 --- a/ruleguard.rules.go +++ b/ruleguard.rules.go @@ -46,6 +46,7 @@ func unconvert(m fluent.Matcher) { func timeeq(m fluent.Matcher) { m.Match("$t0 == $t1").Where(m["t0"].Type.Is("time.Time")).Report("using == with time.Time") m.Match("$t0 != $t1").Where(m["t0"].Type.Is("time.Time")).Report("using != with time.Time") + m.Match(`map[$k]$v`).Where(m["k"].Type.Is("time.Time")).Report("map with time.Time keys are easy to misuse") } // Wrong err in error check @@ -213,10 +214,13 @@ func ifreturn(m fluent.Matcher) { func oddifsequence(m fluent.Matcher) { /* m.Match("if $x { $*_ }; if $x {$*_ }").Report("odd sequence of if test") + m.Match("if $x == $y { $*_ }; if $y == $x {$*_ }").Report("odd sequence of if tests") m.Match("if $x != $y { $*_ }; if $y != $x {$*_ }").Report("odd sequence of if tests") + m.Match("if $x < $y { $*_ }; if $y > $x {$*_ }").Report("odd sequence of if tests") m.Match("if $x <= $y { $*_ }; if $y >= $x {$*_ }").Report("odd sequence of if tests") + m.Match("if $x > $y { $*_ }; if $y < $x {$*_ }").Report("odd sequence of if tests") m.Match("if $x >= $y { $*_ }; if $y <= $x {$*_ }").Report("odd sequence of if tests") */ @@ -357,7 +361,7 @@ func largeloopcopy(m fluent.Matcher) { m.Match( `for $_, $v := range $_ { $*_ }`, ). - Where(m["v"].Type.Size > 512). + Where(m["v"].Type.Size > 1024). Report(`loop copies large value each iteration`) } @@ -454,3 +458,20 @@ func hmacnew(m fluent.Matcher) { ).Where(m["x"].Pure). Report("invalid hash passed to hmac.New()") } + +func writestring(m fluent.Matcher) { + m.Match(`io.WriteString($w, string($b))`). + Where(m["b"].Type.Is("[]byte")). + Suggest("$w.Write($b)") +} + +func badlock(m fluent.Matcher) { + // Shouldn't give many false positives without type filter + // as Lock+Unlock pairs in combination with defer gives us pretty + // a good chance to guess correctly. If we constrain the type to sync.Mutex + // then it'll be harder to match embedded locks and custom methods + // that may forward the call to the sync.Mutex (or other synchronization primitive). + + m.Match(`$mu.Lock(); defer $mu.RUnlock()`).Report(`maybe $mu.RLock() was intended?`) + m.Match(`$mu.RLock(); defer $mu.Unlock()`).Report(`maybe $mu.Lock() was intended?`) +} \ No newline at end of file