diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 6bf650a..618c5ee 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -8,7 +8,7 @@ jobs: name: Build strategy: matrix: - go-version: [1.17.x, 1.18.x] + go-version: [1.18.x, 1.19.x] platform: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.platform }} steps: diff --git a/.golangci.toml b/.golangci.toml index c227c6c..b4f7e6a 100644 --- a/.golangci.toml +++ b/.golangci.toml @@ -1,55 +1,472 @@ [run] deadline = "10m" + tests = true [linters] disable-all = true enable = [ + "asciicheck", + "bidichk", "bodyclose", + "containedctx", + "contextcheck", "deadcode", "depguard", + "durationcheck", "errcheck", + "errchkjson", + "errname", + "errorlint", "exportloopref", + "forbidigo", + #"forcetypeassert", "goconst", "gocyclo", "gocritic", + "godot", "gofumpt", + "gomodguard", "gosec", "gosimple", "govet", + "grouper", "ineffassign", + "lll", + "makezero", + "maintidx", "misspell", "nakedret", + "nilerr", "noctx", "nolintlint", + "nosprintfhostport", + "predeclared", "revive", + "rowserrcheck", "sqlclosecheck", "staticcheck", "structcheck", "stylecheck", + "tenv", + "tparallel", "typecheck", "unconvert", "unparam", "unused", "varcheck", "vetshadow", + "wastedassign", + ] + +# Please note that we only use depguard for stdlib as gomodguard only +# supports modules currently. See https://github.com/ryancurrah/gomodguard/issues/12 +[linters-settings.depguard] + list-type = "blacklist" + include-go-root = true + packages = [ + # ioutil is deprecated. The functions have been moved elsewhere: + # https://golang.org/doc/go1.16#ioutil + "io/ioutil", ] [linters-settings.errcheck] + # Don't allow setting of error to the blank identifier. If there is a legtimate + # reason, there should be a nolint with an explanation. + check-blank = true + + exclude-functions = [ + # If we are rolling back a transaction, we are often already in an error + # state. + '(*database/sql.Tx).Rollback', + + # It is reasonable to ignore errors if Cleanup fails in most cases. + '(*github.com/google/renameio/v2.PendingFile).Cleanup', + + # We often don't care if removing a file failed (e.g., it doesn't exist) + 'os.Remove', + 'os.RemoveAll', + ] + + # Ignoring Close so that we don't have to have a bunch of + # `defer func() { _ = r.Close() }()` constructs when we + # don't actually care about the error. ignore = "Close,fmt:.*" +[linters-settings.errorlint] + errorf = true + asserts = true + comparison = true + +[linters-settings.exhaustive] + default-signifies-exhaustive = true + +[linters-settings.forbidigo] + # Forbid the following identifiers + forbid = [ + "^minFraud*", + "^maxMind*", + ] + +[linters-settings.gocritic] + enabled-checks = [ + "appendAssign", + "appendCombine", + "argOrder", + "assignOp", + "badCall", + "badCond", + "badLock", + "badRegexp", + "badSorting", + "boolExprSimplify", + "builtinShadow", + "builtinShadowDecl", + "captLocal", + "caseOrder", + "codegenComment", + "commentedOutCode", + "commentedOutImport", + "commentFormatting", + "defaultCaseOrder", + # Revive's defer rule already captures this. This caught no extra cases. + # "deferInLoop", + "deferUnlambda", + "deprecatedComment", + "docStub", + "dupArg", + "dupBranchBody", + "dupCase", + "dupImport", + "dupSubExpr", + "dynamicFmtString", + "elseif", + "emptyDecl", + "emptyFallthrough", + "emptyStringTest", + "equalFold", + "evalOrder", + "exitAfterDefer", + "exposedSyncMutex", + "externalErrorReassign", + # Given that all of our code runs on Linux and the / separate should + # work fine, this seems less important. + # "filepathJoin", + "flagDeref", + "flagName", + "hexLiteral", + "ifElseChain", + "importShadow", + "indexAlloc", + "initClause", + "ioutilDeprecated", + "mapKey", + "methodExprCall", + "nestingReduce", + "newDeref", + "nilValReturn", + "octalLiteral", + "offBy1", + "paramTypeCombine", + "preferDecodeRune", + "preferFilepathJoin", + "preferFprint", + "preferStringWriter", + "preferWriteByte", + "ptrToRefParam", + "rangeExprCopy", + "rangeValCopy", + "redundantSprint", + "regexpMust", + "regexpPattern", + # This might be good, but I don't think we want to encourage + # significant changes to regexes as we port stuff from Perl. + # "regexpSimplify", + "ruleguard", + "singleCaseSwitch", + "sliceClear", + "sloppyLen", + # This seems like it might also be good, but a lot of existing code + # fails. + # "sloppyReassign", + "returnAfterHttpError", + "sloppyTypeAssert", + "sortSlice", + "sprintfQuotedString", + "sqlQuery", + "stringsCompare", + "stringXbytes", + "switchTrue", + "syncMapLoadAndDelete", + "timeExprSimplify", + "todoCommentWithoutDetail", + "tooManyResultsChecker", + "truncateCmp", + "typeAssertChain", + "typeDefFirst", + "typeSwitchVar", + "typeUnparen", + "underef", + "unlabelStmt", + "unlambda", + # I am not sure we would want this linter and a lot of existing + # code fails. + # "unnamedResult", + "unnecessaryBlock", + "unnecessaryDefer", + "unslice", + "valSwap", + "weakCond", + "wrapperFunc", + "yodaStyleExpr", + # This requires explanations for "nolint" directives. This would be + # nice for gosec ones, but I am not sure we want it generally unless + # we can get the false positive rate lower. + # "whyNoLint" + ] + [linters-settings.gofumpt] extra-rules = true + lang-version = "1.18" + +[linters-settings.govet] + "enable-all" = true + +[linters-settings.lll] + line-length = 120 + tab-width = 4 + +[linters-settings.nolintlint] + allow-leading-space = false + allow-unused = false + allow-no-explanation = ["lll", "misspell"] + require-explanation = true + require-specific = true + +[linters-settings.revive] + ignore-generated-header = true + severity = "warning" + + # This might be nice but it is so common that it is hard + # to enable. + # [[linters-settings.revive.rules]] + # name = "add-constant" + + # [[linters-settings.revive.rules]] + # name = "argument-limit" + + [[linters-settings.revive.rules]] + name = "atomic" + + [[linters-settings.revive.rules]] + name = "bare-return" + + [[linters-settings.revive.rules]] + name = "blank-imports" + + [[linters-settings.revive.rules]] + name = "bool-literal-in-expr" + + [[linters-settings.revive.rules]] + name = "call-to-gc" + + # [[linters-settings.revive.rules]] + # name = "cognitive-complexity" + + # Probably a good rule, but we have a lot of names that + # only have case differences. + # [[linters-settings.revive.rules]] + # name = "confusing-naming" + + # [[linters-settings.revive.rules]] + # name = "confusing-results" + + [[linters-settings.revive.rules]] + name = "constant-logical-expr" + + [[linters-settings.revive.rules]] + name = "context-as-argument" + + [[linters-settings.revive.rules]] + name = "context-keys-type" + + # [[linters-settings.revive.rules]] + # name = "cyclomatic" + + # [[linters-settings.revive.rules]] + # name = "deep-exit" + + [[linters-settings.revive.rules]] + name = "defer" + + [[linters-settings.revive.rules]] + name = "dot-imports" + + [[linters-settings.revive.rules]] + name = "duplicated-imports" + + [[linters-settings.revive.rules]] + name = "early-return" + + [[linters-settings.revive.rules]] + name = "empty-block" + + [[linters-settings.revive.rules]] + name = "empty-lines" + + [[linters-settings.revive.rules]] + name = "errorf" + + [[linters-settings.revive.rules]] + name = "error-naming" + + [[linters-settings.revive.rules]] + name = "error-return" + + [[linters-settings.revive.rules]] + name = "error-strings" + + [[linters-settings.revive.rules]] + name = "exported" -[issues] -exclude-use-default = false + # [[linters-settings.revive.rules]] + # name = "file-header" - [[issues.exclude-rules]] + # We have a lot of flag parameters. This linter probably makes + # a good point, but we would need some cleanup or a lot of nolints. + # [[linters-settings.revive.rules]] + # name = "flag-parameter" + + # [[linters-settings.revive.rules]] + # name = "function-result-limit" + + [[linters-settings.revive.rules]] + name = "get-return" + + [[linters-settings.revive.rules]] + name = "identical-branches" + + [[linters-settings.revive.rules]] + name = "if-return" + + [[linters-settings.revive.rules]] + name = "imports-blacklist" + + [[linters-settings.revive.rules]] + name = "import-shadowing" + + [[linters-settings.revive.rules]] + name = "increment-decrement" + + [[linters-settings.revive.rules]] + name = "indent-error-flow" + + # [[linters-settings.revive.rules]] + # name = "line-length-limit" + + # [[linters-settings.revive.rules]] + # name = "max-public-structs" + + [[linters-settings.revive.rules]] + name = "modifies-parameter" + + [[linters-settings.revive.rules]] + name = "modifies-value-receiver" + + # We frequently use nested structs, particularly in tests. + # [[linters-settings.revive.rules]] + # name = "nested-structs" + + [[linters-settings.revive.rules]] + name = "optimize-operands-order" + + [[linters-settings.revive.rules]] + name = "package-comments" + + [[linters-settings.revive.rules]] + name = "range" + + [[linters-settings.revive.rules]] + name = "range-val-address" + + [[linters-settings.revive.rules]] + name = "range-val-in-closure" + + [[linters-settings.revive.rules]] + name = "receiver-naming" + + [[linters-settings.revive.rules]] + name = "redefines-builtin-id" + + [[linters-settings.revive.rules]] + name = "string-of-int" + + [[linters-settings.revive.rules]] + name = "struct-tag" + + [[linters-settings.revive.rules]] + name = "superfluous-else" + + [[linters-settings.revive.rules]] + name = "time-naming" + + [[linters-settings.revive.rules]] + name = "unconditional-recursion" + + [[linters-settings.revive.rules]] + name = "unexported-naming" + + [[linters-settings.revive.rules]] + name = "unexported-return" + + # This is covered elsewhere and we want to ignore some + # functions such as fmt.Fprintf. + # [[linters-settings.revive.rules]] + # name = "unhandled-error" + + [[linters-settings.revive.rules]] + name = "unnecessary-stmt" + + [[linters-settings.revive.rules]] + name = "unreachable-code" + + [[linters-settings.revive.rules]] + name = "unused-parameter" + + # We generally have unused receivers in tests for meeting the + # requirements of an interface. + # [[linters-settings.revive.rules]] + # name = "unused-receiver" + + # This probably makes sense after we upgrade to 1.18 + # [[linters-settings.revive.rules]] + # name = "use-any" + + [[linters-settings.revive.rules]] + name = "useless-break" + + [[linters-settings.revive.rules]] + name = "var-declaration" + + [[linters-settings.revive.rules]] + name = "var-naming" + + [[linters-settings.revive.rules]] + name = "waitgroup-by-value" + +[linters-settings.unparam] + check-exported = true + +[[issues.exclude-rules]] linters = [ - "gosec" + "govet" ] - - # G304 - Potential file inclusion via variable (gosec) - # G404 - "Use of weak random number generator (math/rand instead of crypto/rand)" - # We only use this in tests. - text = "G304|G404" + # we want to enable almost all govet rules. It is easier to just filter out + # the ones we don't want: + # + # * fieldalignment - way too noisy. Although it is very useful in particular + # cases where we are trying to use as little memory as possible, having + # it go off on every struct isn't helpful. + # * shadow - although often useful, it complains about _many_ err + # shadowing assignments and some others where shadowing is clear. + text = "^(fieldalignment|shadow)" diff --git a/decoder.go b/decoder.go index c185970..828c57f 100644 --- a/decoder.go +++ b/decoder.go @@ -29,8 +29,8 @@ const ( _Slice // We don't use the next two. They are placeholders. See the spec // for more details. - _Container //nolint: deadcode, varcheck - _Marker //nolint: deadcode, varcheck + _Container //nolint: deadcode, varcheck // above + _Marker //nolint: deadcode, varcheck // above _Bool _Float32 ) diff --git a/decoder_test.go b/decoder_test.go index fd553d3..730e42c 100644 --- a/decoder_test.go +++ b/decoder_test.go @@ -2,8 +2,8 @@ package maxminddb import ( "encoding/hex" - "io/ioutil" "math/big" + "os" "reflect" "strings" "testing" @@ -51,7 +51,7 @@ func TestFloat(t *testing.T) { } func TestInt32(t *testing.T) { - int32 := map[string]interface{}{ + int32s := map[string]interface{}{ "0001": 0, "0401ffffffff": -1, "0101ff": 255, @@ -65,7 +65,7 @@ func TestInt32(t *testing.T) { "04017fffffff": 2147483647, "040180000001": -2147483647, } - validateDecoding(t, int32) + validateDecoding(t, int32s) } func TestMap(t *testing.T) { @@ -120,7 +120,8 @@ func TestString(t *testing.T) { func TestByte(t *testing.T) { b := make(map[string]interface{}) for key, val := range testStrings { - oldCtrl, _ := hex.DecodeString(key[0:2]) + oldCtrl, err := hex.DecodeString(key[0:2]) + require.NoError(t, err) newCtrl := []byte{oldCtrl[0] ^ 0xc0} key = strings.Replace(key, hex.EncodeToString(oldCtrl), hex.EncodeToString(newCtrl), 1) b[key] = []byte(val.(string)) @@ -130,18 +131,18 @@ func TestByte(t *testing.T) { } func TestUint16(t *testing.T) { - uint16 := map[string]interface{}{ + uint16s := map[string]interface{}{ "a0": uint64(0), "a1ff": uint64(255), "a201f4": uint64(500), "a22a78": uint64(10872), "a2ffff": uint64(65535), } - validateDecoding(t, uint16) + validateDecoding(t, uint16s) } func TestUint32(t *testing.T) { - uint32 := map[string]interface{}{ + uint32s := map[string]interface{}{ "c0": uint64(0), "c1ff": uint64(255), "c201f4": uint64(500), @@ -150,7 +151,7 @@ func TestUint32(t *testing.T) { "c3ffffff": uint64(16777215), "c4ffffffff": uint64(4294967295), } - validateDecoding(t, uint32) + validateDecoding(t, uint32s) } func TestUint64(t *testing.T) { @@ -205,11 +206,12 @@ func powBigInt(bi *big.Int, pow uint) *big.Int { func validateDecoding(t *testing.T, tests map[string]interface{}) { for inputStr, expected := range tests { - inputBytes, _ := hex.DecodeString(inputStr) + inputBytes, err := hex.DecodeString(inputStr) + require.NoError(t, err) d := decoder{inputBytes} var result interface{} - _, err := d.decode(0, reflect.ValueOf(&result), 0) + _, err = d.decode(0, reflect.ValueOf(&result), 0) assert.NoError(t, err) if !reflect.DeepEqual(result, expected) { @@ -220,7 +222,7 @@ func validateDecoding(t *testing.T, tests map[string]interface{}) { } func TestPointers(t *testing.T) { - bytes, err := ioutil.ReadFile(testFile("maps-with-pointers.raw")) + bytes, err := os.ReadFile(testFile("maps-with-pointers.raw")) require.NoError(t, err) d := decoder{bytes} diff --git a/deserializer_test.go b/deserializer_test.go index 8b15fee..2412248 100644 --- a/deserializer_test.go +++ b/deserializer_test.go @@ -30,7 +30,7 @@ type testDeserializer struct { key *string } -func (d *testDeserializer) ShouldSkip(offset uintptr) (bool, error) { +func (d *testDeserializer) ShouldSkip(_ uintptr) (bool, error) { return false, nil } @@ -38,10 +38,11 @@ func (d *testDeserializer) StartSlice(size uint) error { return d.add(make([]interface{}, size)) } -func (d *testDeserializer) StartMap(size uint) error { +func (d *testDeserializer) StartMap(_ uint) error { return d.add(map[string]interface{}{}) } +//nolint:unparam // This is to meet the requirements of the interface. func (d *testDeserializer) End() error { d.stack = d.stack[:len(d.stack)-1] return nil diff --git a/example_test.go b/example_test.go index d936e34..8e8587c 100644 --- a/example_test.go +++ b/example_test.go @@ -76,25 +76,29 @@ func ExampleReader_Networks() { log.Panic(networks.Err()) } // Output: - // 1.0.0.0/24: Dialup - // 1.0.1.0/24: Cable/DSL - // 1.0.2.0/23: Dialup - // 1.0.4.0/22: Dialup - // 1.0.8.0/21: Dialup - // 1.0.16.0/20: Dialup - // 1.0.32.0/19: Dialup - // 1.0.64.0/18: Dialup - // 1.0.128.0/17: Dialup + // 1.0.0.0/24: Cable/DSL + // 1.0.1.0/24: Cellular + // 1.0.2.0/23: Cable/DSL + // 1.0.4.0/22: Cable/DSL + // 1.0.8.0/21: Cable/DSL + // 1.0.16.0/20: Cable/DSL + // 1.0.32.0/19: Cable/DSL + // 1.0.64.0/18: Cable/DSL + // 1.0.128.0/17: Cable/DSL + // 2.125.160.216/29: Cable/DSL + // 67.43.156.0/24: Cellular // 80.214.0.0/20: Cellular // 96.1.0.0/16: Cable/DSL // 96.10.0.0/15: Cable/DSL // 96.69.0.0/16: Cable/DSL // 96.94.0.0/15: Cable/DSL // 108.96.0.0/11: Cellular - // 175.16.199.0/24: Dialup + // 149.101.100.0/28: Cellular + // 175.16.199.0/24: Cable/DSL // 187.156.138.0/24: Cable/DSL // 201.243.200.0/24: Corporate // 207.179.48.0/20: Cellular + // 216.160.83.56/29: Corporate // 2003::/24: Cable/DSL } @@ -129,13 +133,13 @@ func ExampleReader_NetworksWithin() { } // Output: - // 1.0.0.0/24: Dialup - // 1.0.1.0/24: Cable/DSL - // 1.0.2.0/23: Dialup - // 1.0.4.0/22: Dialup - // 1.0.8.0/21: Dialup - // 1.0.16.0/20: Dialup - // 1.0.32.0/19: Dialup - // 1.0.64.0/18: Dialup - // 1.0.128.0/17: Dialup + // 1.0.0.0/24: Cable/DSL + // 1.0.1.0/24: Cellular + // 1.0.2.0/23: Cable/DSL + // 1.0.4.0/22: Cable/DSL + // 1.0.8.0/21: Cable/DSL + // 1.0.16.0/20: Cable/DSL + // 1.0.32.0/19: Cable/DSL + // 1.0.64.0/18: Cable/DSL + // 1.0.128.0/17: Cable/DSL } diff --git a/go.mod b/go.mod index 9bfa6dd..dcce7e4 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,10 @@ module github.com/oschwald/maxminddb-golang -go 1.17 +go 1.18 require ( github.com/stretchr/testify v1.7.3 - golang.org/x/sys v0.0.0-20220325203850-36772127a21f + golang.org/x/sys v0.0.0-20220804214406-8e32c043e418 ) require ( diff --git a/go.sum b/go.sum index 54cecef..0afa47d 100644 --- a/go.sum +++ b/go.sum @@ -10,6 +10,8 @@ github.com/stretchr/testify v1.7.3 h1:dAm0YRdRQlWojc3CrCRgPBzG5f941d0zvAKu7qY4e+ github.com/stretchr/testify v1.7.3/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= golang.org/x/sys v0.0.0-20220325203850-36772127a21f h1:TrmogKRsSOxRMJbLYGrB4SBbW+LJcEllYBLME5Zk5pU= golang.org/x/sys v0.0.0-20220325203850-36772127a21f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220804214406-8e32c043e418 h1:9vYwv7OjYaky/tlAeD7C4oC9EsPTlaFl1H2jS++V+ME= +golang.org/x/sys v0.0.0-20220804214406-8e32c043e418/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/reader.go b/reader.go index 37de357..263cf64 100644 --- a/reader.go +++ b/reader.go @@ -241,7 +241,7 @@ func (r *Reader) decode(offset uintptr, result interface{}) error { func (r *Reader) lookupPointer(ip net.IP) (uint, int, net.IP, error) { if ip == nil { - return 0, 0, ip, errors.New("IP passed to Lookup cannot be nil") + return 0, 0, nil, errors.New("IP passed to Lookup cannot be nil") } ipV4Address := ip.To4() diff --git a/reader_other.go b/reader_other.go index 02eda4f..0ed9de1 100644 --- a/reader_other.go +++ b/reader_other.go @@ -34,13 +34,15 @@ func Open(file string) (*Reader, error) { } if err := mapFile.Close(); err != nil { - _ = munmap(mmap) + //nolint:errcheck // we prefer to return the original error + munmap(mmap) return nil, err } reader, err := FromBytes(mmap) if err != nil { - _ = munmap(mmap) + //nolint:errcheck // we prefer to return the original error + munmap(mmap) return nil, err } diff --git a/reader_test.go b/reader_test.go index 403dcf3..9eabea1 100644 --- a/reader_test.go +++ b/reader_test.go @@ -3,10 +3,10 @@ package maxminddb import ( "errors" "fmt" - "io/ioutil" "math/big" "math/rand" "net" + "os" "path/filepath" "testing" "time" @@ -44,7 +44,8 @@ func TestReaderBytes(t *testing.T) { ipVersion, recordSize, ) - bytes, _ := ioutil.ReadFile(fileName) + bytes, err := os.ReadFile(fileName) + require.NoError(t, err) reader, err := FromBytes(bytes) require.NoError(t, err, "unexpected error while opening bytes: %v", err) @@ -246,7 +247,6 @@ func checkDecodingToInterface(t *testing.T, recordInterface interface{}) { assert.Equal(t, bigInt, record["uint128"]) } -//nolint: maligned type TestType struct { Array []uint `maxminddb:"array"` Boolean bool `maxminddb:"boolean"` @@ -557,30 +557,33 @@ func TestNonDatabase(t *testing.T) { } func TestDecodingToNonPointer(t *testing.T) { - reader, _ := Open(testFile("MaxMind-DB-test-decoder.mmdb")) + reader, err := Open(testFile("MaxMind-DB-test-decoder.mmdb")) + require.NoError(t, err) var recordInterface interface{} - err := reader.Lookup(net.ParseIP("::1.1.1.0"), recordInterface) + err = reader.Lookup(net.ParseIP("::1.1.1.0"), recordInterface) assert.Equal(t, "result param must be a pointer", err.Error()) assert.NoError(t, reader.Close(), "error on close") } func TestNilLookup(t *testing.T) { - reader, _ := Open(testFile("MaxMind-DB-test-decoder.mmdb")) + reader, err := Open(testFile("MaxMind-DB-test-decoder.mmdb")) + require.NoError(t, err) var recordInterface interface{} - err := reader.Lookup(nil, recordInterface) + err = reader.Lookup(nil, recordInterface) assert.Equal(t, "IP passed to Lookup cannot be nil", err.Error()) assert.NoError(t, reader.Close(), "error on close") } func TestUsingClosedDatabase(t *testing.T) { - reader, _ := Open(testFile("MaxMind-DB-test-decoder.mmdb")) + reader, err := Open(testFile("MaxMind-DB-test-decoder.mmdb")) + require.NoError(t, err) require.NoError(t, reader.Close()) var recordInterface interface{} - err := reader.Lookup(nil, recordInterface) + err = reader.Lookup(nil, recordInterface) assert.Equal(t, "cannot call Lookup on a closed database", err.Error()) _, err = reader.LookupOffset(nil) @@ -714,6 +717,7 @@ func BenchmarkInterfaceLookup(b *testing.B) { db, err := Open("GeoLite2-City.mmdb") require.NoError(b, err) + //nolint:gosec // this is a test r := rand.New(rand.NewSource(time.Now().UnixNano())) var result interface{} @@ -732,6 +736,7 @@ func BenchmarkInterfaceLookupNetwork(b *testing.B) { db, err := Open("GeoLite2-City.mmdb") require.NoError(b, err) + //nolint:gosec // this is a test r := rand.New(rand.NewSource(time.Now().UnixNano())) var result interface{} @@ -800,6 +805,7 @@ func BenchmarkCityLookup(b *testing.B) { db, err := Open("GeoLite2-City.mmdb") require.NoError(b, err) + //nolint:gosec // this is a test r := rand.New(rand.NewSource(time.Now().UnixNano())) var result fullCity @@ -818,6 +824,7 @@ func BenchmarkCityLookupNetwork(b *testing.B) { db, err := Open("GeoLite2-City.mmdb") require.NoError(b, err) + //nolint:gosec // this is a test r := rand.New(rand.NewSource(time.Now().UnixNano())) var result fullCity @@ -842,6 +849,7 @@ func BenchmarkCountryCode(b *testing.B) { } `maxminddb:"country"` } + //nolint:gosec // this is a test r := rand.New(rand.NewSource(0)) var result MinCountry diff --git a/test-data b/test-data index c46c33c..3e225a8 160000 --- a/test-data +++ b/test-data @@ -1 +1 @@ -Subproject commit c46c33c3c598c648013e2aa7458f8492f4ecfcce +Subproject commit 3e225a82e492a58eef738ef2b6e94aa4f50ef932 diff --git a/verifier.go b/verifier.go index daa231d..88381d7 100644 --- a/verifier.go +++ b/verifier.go @@ -157,11 +157,14 @@ func (v *verifier) verifyDataSection(offsets map[uint]bool) error { pointer := offset - if _, ok := offsets[pointer]; ok { - delete(offsets, pointer) - } else { - return newInvalidDatabaseError("found data (%v) at %v that the search tree does not point to", data, pointer) + if _, ok := offsets[pointer]; !ok { + return newInvalidDatabaseError( + "found data (%v) at %v that the search tree does not point to", + data, + pointer, + ) } + delete(offsets, pointer) offset = newOffset }