mirror of
https://github.com/DNSCrypt/dnscrypt-proxy.git
synced 2025-04-06 06:37:36 +03:00
Update deps
This commit is contained in:
parent
f033bb3034
commit
5a091c6da4
1997 changed files with 368830 additions and 2045 deletions
21
vendor/github.com/polyfloyd/go-errorlint/LICENSE
generated
vendored
Normal file
21
vendor/github.com/polyfloyd/go-errorlint/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2019 polyfloyd
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
137
vendor/github.com/polyfloyd/go-errorlint/errorlint/allowed.go
generated
vendored
Normal file
137
vendor/github.com/polyfloyd/go-errorlint/errorlint/allowed.go
generated
vendored
Normal file
|
@ -0,0 +1,137 @@
|
|||
package errorlint
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/types"
|
||||
)
|
||||
|
||||
var allowedErrors = []struct {
|
||||
err string
|
||||
fun string
|
||||
}{
|
||||
// pkg/archive/tar
|
||||
{err: "io.EOF", fun: "(*tar.Reader).Next"},
|
||||
{err: "io.EOF", fun: "(*tar.Reader).Read"},
|
||||
// pkg/bufio
|
||||
{err: "io.EOF", fun: "(*bufio.Reader).Read"},
|
||||
{err: "io.EOF", fun: "(*bufio.Reader).ReadByte"},
|
||||
{err: "io.EOF", fun: "(*bufio.Reader).ReadBytes"},
|
||||
{err: "io.EOF", fun: "(*bufio.Reader).ReadSlice"},
|
||||
{err: "io.EOF", fun: "(*bufio.Reader).ReadString"},
|
||||
{err: "io.EOF", fun: "(*bufio.Scanner).Scan"},
|
||||
// pkg/bytes
|
||||
{err: "io.EOF", fun: "(*bytes.Buffer).Read"},
|
||||
{err: "io.EOF", fun: "(*bytes.Buffer).ReadByte"},
|
||||
{err: "io.EOF", fun: "(*bytes.Buffer).ReadBytes"},
|
||||
{err: "io.EOF", fun: "(*bytes.Buffer).ReadRune"},
|
||||
{err: "io.EOF", fun: "(*bytes.Buffer).ReadString"},
|
||||
// pkg/database/sql
|
||||
{err: "sql.ErrNoRows", fun: "(*database/sql.Row).Scan"},
|
||||
// pkg/io
|
||||
{err: "io.EOF", fun: "(io.Reader).Read"},
|
||||
{err: "io.ErrClosedPipe", fun: "(*io.PipeWriter).Write"},
|
||||
{err: "io.ErrShortBuffer", fun: "io.ReadAtLeast"},
|
||||
{err: "io.ErrUnexpectedEOF", fun: "io.ReadAtLeast"},
|
||||
{err: "io.ErrUnexpectedEOF", fun: "io.ReadFull"},
|
||||
// pkg/os
|
||||
{err: "io.EOF", fun: "(*os.File).Read"},
|
||||
{err: "io.EOF", fun: "(*os.File).ReadAt"},
|
||||
{err: "io.EOF", fun: "(*os.File).ReadDir"},
|
||||
{err: "io.EOF", fun: "(*os.File).Readdir"},
|
||||
{err: "io.EOF", fun: "(*os.File).Readdirnames"},
|
||||
// pkg/strings
|
||||
{err: "io.EOF", fun: "(*strings.Reader).Read"},
|
||||
{err: "io.EOF", fun: "(*strings.Reader).ReadAt"},
|
||||
{err: "io.EOF", fun: "(*strings.Reader).ReadByte"},
|
||||
{err: "io.EOF", fun: "(*strings.Reader).ReadRune"},
|
||||
}
|
||||
|
||||
func isAllowedErrorComparison(info types.Info, binExpr *ast.BinaryExpr) bool {
|
||||
var errName string // `<package>.<name>`, e.g. `io.EOF`
|
||||
var callExpr *ast.CallExpr
|
||||
|
||||
// Figure out which half of the expression is the returned error and which
|
||||
// half is the presumed error declaration.
|
||||
for _, expr := range []ast.Expr{binExpr.X, binExpr.Y} {
|
||||
switch t := expr.(type) {
|
||||
case *ast.SelectorExpr:
|
||||
// A selector which we assume refers to a staticaly declared error
|
||||
// in a package.
|
||||
errName = selectorToString(t)
|
||||
case *ast.Ident:
|
||||
// Identifier, most likely to be the `err` variable or whatever
|
||||
// produces it.
|
||||
callExpr = assigningCallExpr(info, t)
|
||||
case *ast.CallExpr:
|
||||
callExpr = t
|
||||
}
|
||||
}
|
||||
|
||||
// Unimplemented or not sure, disallow the expression.
|
||||
if errName == "" || callExpr == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// Find the expression that last assigned the subject identifier.
|
||||
functionSelector, ok := callExpr.Fun.(*ast.SelectorExpr)
|
||||
if !ok {
|
||||
// If the function is not a selector it is not an Std function that is
|
||||
// allowed.
|
||||
return false
|
||||
}
|
||||
var functionName string
|
||||
if sel, ok := info.Selections[functionSelector]; ok {
|
||||
functionName = fmt.Sprintf("(%s).%s", sel.Recv(), sel.Obj().Name())
|
||||
} else {
|
||||
// If there is no selection, assume it is a package.
|
||||
functionName = selectorToString(callExpr.Fun.(*ast.SelectorExpr))
|
||||
}
|
||||
|
||||
for _, w := range allowedErrors {
|
||||
if w.fun == functionName && w.err == errName {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func assigningCallExpr(info types.Info, subject *ast.Ident) *ast.CallExpr {
|
||||
if subject.Obj == nil {
|
||||
return nil
|
||||
}
|
||||
switch declT := subject.Obj.Decl.(type) {
|
||||
case *ast.AssignStmt:
|
||||
// The identifier is LHS of an assignment.
|
||||
assignment := declT
|
||||
|
||||
assigningExpr := assignment.Rhs[0]
|
||||
// If the assignment is comprised of multiple expressions, find out
|
||||
// which LHS expression we should use by finding its index in the LHS.
|
||||
if len(assignment.Rhs) > 1 {
|
||||
for i, lhs := range assignment.Lhs {
|
||||
if subject.Name == lhs.(*ast.Ident).Name {
|
||||
assigningExpr = assignment.Rhs[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch assignT := assigningExpr.(type) {
|
||||
case *ast.CallExpr:
|
||||
// Found the function call.
|
||||
return assignT
|
||||
case *ast.Ident:
|
||||
// The subject was the result of assigning from another identifier.
|
||||
return assigningCallExpr(info, assignT)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func selectorToString(selExpr *ast.SelectorExpr) string {
|
||||
if ident, ok := selExpr.X.(*ast.Ident); ok {
|
||||
return ident.Name + "." + selExpr.Sel.Name
|
||||
}
|
||||
return ""
|
||||
}
|
52
vendor/github.com/polyfloyd/go-errorlint/errorlint/analysis.go
generated
vendored
Normal file
52
vendor/github.com/polyfloyd/go-errorlint/errorlint/analysis.go
generated
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
package errorlint
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"sort"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
)
|
||||
|
||||
func NewAnalyzer() *analysis.Analyzer {
|
||||
return &analysis.Analyzer{
|
||||
Name: "errorlint",
|
||||
Doc: "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.",
|
||||
Run: run,
|
||||
Flags: flagSet,
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
flagSet flag.FlagSet
|
||||
checkComparison bool
|
||||
checkAsserts bool
|
||||
checkErrorf bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
flagSet.BoolVar(&checkComparison, "comparison", true, "Check for plain error comparisons")
|
||||
flagSet.BoolVar(&checkAsserts, "asserts", true, "Check for plain type assertions and type switches")
|
||||
flagSet.BoolVar(&checkErrorf, "errorf", false, "Check whether fmt.Errorf uses the %w verb for formatting errors. See the readme for caveats")
|
||||
}
|
||||
|
||||
func run(pass *analysis.Pass) (interface{}, error) {
|
||||
lints := []Lint{}
|
||||
if checkComparison {
|
||||
l := LintErrorComparisons(pass.Fset, *pass.TypesInfo)
|
||||
lints = append(lints, l...)
|
||||
}
|
||||
if checkAsserts {
|
||||
l := LintErrorTypeAssertions(pass.Fset, *pass.TypesInfo)
|
||||
lints = append(lints, l...)
|
||||
}
|
||||
if checkErrorf {
|
||||
l := LintFmtErrorfCalls(pass.Fset, *pass.TypesInfo)
|
||||
lints = append(lints, l...)
|
||||
}
|
||||
sort.Sort(ByPosition(lints))
|
||||
|
||||
for _, l := range lints {
|
||||
pass.Report(analysis.Diagnostic{Pos: l.Pos, Message: l.Message})
|
||||
}
|
||||
return nil, nil
|
||||
}
|
249
vendor/github.com/polyfloyd/go-errorlint/errorlint/lint.go
generated
vendored
Normal file
249
vendor/github.com/polyfloyd/go-errorlint/errorlint/lint.go
generated
vendored
Normal file
|
@ -0,0 +1,249 @@
|
|||
package errorlint
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
type Lint struct {
|
||||
Message string
|
||||
Pos token.Pos
|
||||
}
|
||||
|
||||
type ByPosition []Lint
|
||||
|
||||
func (l ByPosition) Len() int { return len(l) }
|
||||
func (l ByPosition) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
|
||||
|
||||
func (l ByPosition) Less(i, j int) bool {
|
||||
return l[i].Pos < l[j].Pos
|
||||
}
|
||||
|
||||
func LintFmtErrorfCalls(fset *token.FileSet, info types.Info) []Lint {
|
||||
lints := []Lint{}
|
||||
for expr, t := range info.Types {
|
||||
// Search for error expressions that are the result of fmt.Errorf
|
||||
// invocations.
|
||||
if t.Type.String() != "error" {
|
||||
continue
|
||||
}
|
||||
call, ok := isFmtErrorfCallExpr(info, expr)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
// Find all % fields in the format string.
|
||||
formatVerbs, ok := printfFormatStringVerbs(info, call)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
// For any arguments that are errors, check whether the wrapping verb
|
||||
// is used. Only one %w verb may be used in a single format string at a
|
||||
// time, so we stop after finding a correct %w.
|
||||
var lintArg ast.Expr
|
||||
args := call.Args[1:]
|
||||
for i := 0; i < len(args) && i < len(formatVerbs); i++ {
|
||||
if info.Types[args[i]].Type.String() != "error" && !isErrorStringCall(info, args[i]) {
|
||||
continue
|
||||
}
|
||||
|
||||
if formatVerbs[i] == "%w" {
|
||||
lintArg = nil
|
||||
break
|
||||
}
|
||||
|
||||
if lintArg == nil {
|
||||
lintArg = args[i]
|
||||
}
|
||||
}
|
||||
if lintArg != nil {
|
||||
lints = append(lints, Lint{
|
||||
Message: "non-wrapping format verb for fmt.Errorf. Use `%w` to format errors",
|
||||
Pos: lintArg.Pos(),
|
||||
})
|
||||
}
|
||||
}
|
||||
return lints
|
||||
}
|
||||
|
||||
// isErrorStringCall tests whether the expression is a string expression that
|
||||
// is the result of an `(error).Error()` method call.
|
||||
func isErrorStringCall(info types.Info, expr ast.Expr) bool {
|
||||
if info.Types[expr].Type.String() == "string" {
|
||||
if call, ok := expr.(*ast.CallExpr); ok {
|
||||
if callSel, ok := call.Fun.(*ast.SelectorExpr); ok {
|
||||
fun := info.Uses[callSel.Sel].(*types.Func)
|
||||
return fun.Type().String() == "func() string" && fun.Name() == "Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func printfFormatStringVerbs(info types.Info, call *ast.CallExpr) ([]string, bool) {
|
||||
if len(call.Args) <= 1 {
|
||||
return nil, false
|
||||
}
|
||||
strLit, ok := call.Args[0].(*ast.BasicLit)
|
||||
if !ok {
|
||||
// Ignore format strings that are not literals.
|
||||
return nil, false
|
||||
}
|
||||
formatString := constant.StringVal(info.Types[strLit].Value)
|
||||
|
||||
// Naive format string argument verb. This does not take modifiers such as
|
||||
// padding into account...
|
||||
re := regexp.MustCompile(`%[^%]`)
|
||||
return re.FindAllString(formatString, -1), true
|
||||
}
|
||||
|
||||
func isFmtErrorfCallExpr(info types.Info, expr ast.Expr) (*ast.CallExpr, bool) {
|
||||
call, ok := expr.(*ast.CallExpr)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
fn, ok := call.Fun.(*ast.SelectorExpr)
|
||||
if !ok {
|
||||
// TODO: Support fmt.Errorf variable aliases?
|
||||
return nil, false
|
||||
}
|
||||
obj := info.Uses[fn.Sel]
|
||||
|
||||
pkg := obj.Pkg()
|
||||
if pkg != nil && pkg.Name() == "fmt" && obj.Name() == "Errorf" {
|
||||
return call, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func LintErrorComparisons(fset *token.FileSet, info types.Info) []Lint {
|
||||
lints := []Lint{}
|
||||
|
||||
for expr := range info.Types {
|
||||
// Find == and != operations.
|
||||
binExpr, ok := expr.(*ast.BinaryExpr)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if binExpr.Op != token.EQL && binExpr.Op != token.NEQ {
|
||||
continue
|
||||
}
|
||||
// Comparing errors with nil is okay.
|
||||
if isNilComparison(binExpr) {
|
||||
continue
|
||||
}
|
||||
// Find comparisons of which one side is a of type error.
|
||||
if !isErrorComparison(info, binExpr) {
|
||||
continue
|
||||
}
|
||||
|
||||
if isAllowedErrorComparison(info, binExpr) {
|
||||
continue
|
||||
}
|
||||
|
||||
lints = append(lints, Lint{
|
||||
Message: fmt.Sprintf("comparing with %s will fail on wrapped errors. Use errors.Is to check for a specific error", binExpr.Op),
|
||||
Pos: binExpr.Pos(),
|
||||
})
|
||||
}
|
||||
|
||||
for scope := range info.Scopes {
|
||||
// Find value switch blocks.
|
||||
switchStmt, ok := scope.(*ast.SwitchStmt)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
// Check whether the switch operates on an error type.
|
||||
if switchStmt.Tag == nil {
|
||||
continue
|
||||
}
|
||||
tagType := info.Types[switchStmt.Tag]
|
||||
if tagType.Type.String() != "error" {
|
||||
continue
|
||||
}
|
||||
|
||||
lints = append(lints, Lint{
|
||||
Message: "switch on an error will fail on wrapped errors. Use errors.Is to check for specific errors",
|
||||
Pos: switchStmt.Pos(),
|
||||
})
|
||||
}
|
||||
|
||||
return lints
|
||||
}
|
||||
|
||||
func isNilComparison(binExpr *ast.BinaryExpr) bool {
|
||||
if ident, ok := binExpr.X.(*ast.Ident); ok && ident.Name == "nil" {
|
||||
return true
|
||||
}
|
||||
if ident, ok := binExpr.Y.(*ast.Ident); ok && ident.Name == "nil" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isErrorComparison(info types.Info, binExpr *ast.BinaryExpr) bool {
|
||||
tx := info.Types[binExpr.X]
|
||||
ty := info.Types[binExpr.Y]
|
||||
return tx.Type.String() == "error" || ty.Type.String() == "error"
|
||||
}
|
||||
|
||||
func LintErrorTypeAssertions(fset *token.FileSet, info types.Info) []Lint {
|
||||
lints := []Lint{}
|
||||
|
||||
for expr := range info.Types {
|
||||
// Find type assertions.
|
||||
typeAssert, ok := expr.(*ast.TypeAssertExpr)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
// Find type assertions that operate on values of type error.
|
||||
if !isErrorTypeAssertion(info, typeAssert) {
|
||||
continue
|
||||
}
|
||||
|
||||
lints = append(lints, Lint{
|
||||
Message: "type assertion on error will fail on wrapped errors. Use errors.As to check for specific errors",
|
||||
Pos: typeAssert.Pos(),
|
||||
})
|
||||
}
|
||||
|
||||
for scope := range info.Scopes {
|
||||
// Find type switches.
|
||||
typeSwitch, ok := scope.(*ast.TypeSwitchStmt)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
// Find the type assertion in the type switch.
|
||||
var typeAssert *ast.TypeAssertExpr
|
||||
switch t := typeSwitch.Assign.(type) {
|
||||
case *ast.ExprStmt:
|
||||
typeAssert = t.X.(*ast.TypeAssertExpr)
|
||||
case *ast.AssignStmt:
|
||||
typeAssert = t.Rhs[0].(*ast.TypeAssertExpr)
|
||||
}
|
||||
|
||||
// Check whether the type switch is on a value of type error.
|
||||
if !isErrorTypeAssertion(info, typeAssert) {
|
||||
continue
|
||||
}
|
||||
|
||||
lints = append(lints, Lint{
|
||||
Message: "type switch on error will fail on wrapped errors. Use errors.As to check for specific errors",
|
||||
Pos: typeAssert.Pos(),
|
||||
})
|
||||
}
|
||||
|
||||
return lints
|
||||
}
|
||||
|
||||
func isErrorTypeAssertion(info types.Info, typeAssert *ast.TypeAssertExpr) bool {
|
||||
t := info.Types[typeAssert.X]
|
||||
return t.Type.String() == "error"
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue