mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-06 20:13:59 -05:00
Extend httperror analyzer to more functions (#16186)
**What type of PR is this?** Tooling **What does this PR do? Why is it needed?** Renames `httperror` analyzer to `httpwriter` and extends it to the following functions: - `WriteError` - `WriteJson` - `WriteSsz` _**NOTE: The PR is currently red because the fix in https://github.com/OffchainLabs/prysm/pull/16175 must be merged first**_ **Acknowledgements** - [x] I have read [CONTRIBUTING.md](https://github.com/prysmaticlabs/prysm/blob/develop/CONTRIBUTING.md). - [x] I have included a uniquely named [changelog fragment file](https://github.com/prysmaticlabs/prysm/blob/develop/CONTRIBUTING.md#maintaining-changelogmd). - [x] I have added a description with sufficient context for reviewers to understand this PR. - [x] I have tested that my changes work as expected and I added a testing plan to the PR description (if applicable).
This commit is contained in:
@@ -193,7 +193,7 @@ nogo(
|
|||||||
"//tools/analyzers/featureconfig:go_default_library",
|
"//tools/analyzers/featureconfig:go_default_library",
|
||||||
"//tools/analyzers/gocognit:go_default_library",
|
"//tools/analyzers/gocognit:go_default_library",
|
||||||
"//tools/analyzers/ineffassign:go_default_library",
|
"//tools/analyzers/ineffassign:go_default_library",
|
||||||
"//tools/analyzers/httperror:go_default_library",
|
"//tools/analyzers/httpwriter:go_default_library",
|
||||||
"//tools/analyzers/interfacechecker:go_default_library",
|
"//tools/analyzers/interfacechecker:go_default_library",
|
||||||
"//tools/analyzers/logcapitalization:go_default_library",
|
"//tools/analyzers/logcapitalization:go_default_library",
|
||||||
"//tools/analyzers/logruswitherror:go_default_library",
|
"//tools/analyzers/logruswitherror:go_default_library",
|
||||||
|
|||||||
3
changelog/radek_extend-http-analyzer.md
Normal file
3
changelog/radek_extend-http-analyzer.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
### Changed
|
||||||
|
|
||||||
|
- Extend `httperror` analyzer to more functions.
|
||||||
@@ -43,6 +43,7 @@ func WriteJson(w http.ResponseWriter, v any) {
|
|||||||
func WriteSsz(w http.ResponseWriter, respSsz []byte) {
|
func WriteSsz(w http.ResponseWriter, respSsz []byte) {
|
||||||
w.Header().Set("Content-Length", strconv.Itoa(len(respSsz)))
|
w.Header().Set("Content-Length", strconv.Itoa(len(respSsz)))
|
||||||
w.Header().Set("Content-Type", api.OctetStreamMediaType)
|
w.Header().Set("Content-Type", api.OctetStreamMediaType)
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
if _, err := io.Copy(w, io.NopCloser(bytes.NewReader(respSsz))); err != nil {
|
if _, err := io.Copy(w, io.NopCloser(bytes.NewReader(respSsz))); err != nil {
|
||||||
log.WithError(err).Error("Could not write response message")
|
log.WithError(err).Error("Could not write response message")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ load("@prysm//tools/go:def.bzl", "go_library")
|
|||||||
go_library(
|
go_library(
|
||||||
name = "go_default_library",
|
name = "go_default_library",
|
||||||
srcs = ["analyzer.go"],
|
srcs = ["analyzer.go"],
|
||||||
importpath = "github.com/OffchainLabs/prysm/v7/tools/analyzers/httperror",
|
importpath = "github.com/OffchainLabs/prysm/v7/tools/analyzers/httpwriter",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
"@org_golang_x_tools//go/analysis:go_default_library",
|
"@org_golang_x_tools//go/analysis:go_default_library",
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package httperror
|
package httpwriter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"go/ast"
|
"go/ast"
|
||||||
@@ -9,8 +9,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "httperror",
|
Name: "httpwriter",
|
||||||
Doc: "Ensures calls to httputil.HandleError are immediately followed by a return statement.",
|
Doc: "Ensures that httputil functions which make use of the writer are immediately followed by a return statement.",
|
||||||
Requires: []*analysis.Analyzer{
|
Requires: []*analysis.Analyzer{
|
||||||
inspect.Analyzer,
|
inspect.Analyzer,
|
||||||
},
|
},
|
||||||
@@ -99,7 +99,7 @@ func checkBlock(pass *analysis.Pass, fn *ast.FuncDecl, block *ast.BlockStmt, nex
|
|||||||
|
|
||||||
// Now check the current statement itself: is it (or does it contain) a direct call to httputil.HandleError?
|
// Now check the current statement itself: is it (or does it contain) a direct call to httputil.HandleError?
|
||||||
// We only consider ExprStmt that are direct CallExpr to httputil.HandleError.
|
// We only consider ExprStmt that are direct CallExpr to httputil.HandleError.
|
||||||
call := findHandleErrorCall(stmt)
|
call, name := findHandleErrorCall(stmt)
|
||||||
if call == nil {
|
if call == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -121,7 +121,7 @@ func checkBlock(pass *analysis.Pass, fn *ast.FuncDecl, block *ast.BlockStmt, nex
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// otherwise it's not a return (even if it's an if/for etc) -> violation
|
// otherwise it's not a return (even if it's an if/for etc) -> violation
|
||||||
pass.Reportf(stmt.Pos(), "call to httputil.HandleError must be immediately followed by a return statement")
|
pass.Reportf(stmt.Pos(), "call to httputil.%s must be immediately followed by a return statement", name)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,31 +133,33 @@ func checkBlock(pass *analysis.Pass, fn *ast.FuncDecl, block *ast.BlockStmt, nex
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Non-void function and it's the last statement → violation
|
// Non-void function and it's the last statement → violation
|
||||||
pass.Reportf(stmt.Pos(), "call to httputil.HandleError must be followed by return because function has return values")
|
pass.Reportf(stmt.Pos(), "call to httputil.%s must be immediately followed by a return statement", name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// findHandleErrorCall returns the call expression if stmt is a direct call to httputil.HandleError(...),
|
// findHandleErrorCall returns the call expression if stmt is a direct call to httputil.HandleError(...),
|
||||||
// otherwise nil. We only match direct ExprStmt -> CallExpr -> SelectorExpr where selector is httputil.HandleError.
|
// otherwise nil. We only match direct ExprStmt -> CallExpr -> SelectorExpr where selector is httputil.HandleError.
|
||||||
func findHandleErrorCall(stmt ast.Stmt) *ast.CallExpr {
|
func findHandleErrorCall(stmt ast.Stmt) (*ast.CallExpr, string) {
|
||||||
es, ok := stmt.(*ast.ExprStmt)
|
es, ok := stmt.(*ast.ExprStmt)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil, ""
|
||||||
}
|
}
|
||||||
call, ok := es.X.(*ast.CallExpr)
|
call, ok := es.X.(*ast.CallExpr)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil, ""
|
||||||
}
|
}
|
||||||
sel, ok := call.Fun.(*ast.SelectorExpr)
|
sel, ok := call.Fun.(*ast.SelectorExpr)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil, ""
|
||||||
}
|
}
|
||||||
pkgIdent, ok := sel.X.(*ast.Ident)
|
pkgIdent, ok := sel.X.(*ast.Ident)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil, ""
|
||||||
}
|
}
|
||||||
if pkgIdent.Name == "httputil" && sel.Sel.Name == "HandleError" {
|
selectorName := sel.Sel.Name
|
||||||
return call
|
if pkgIdent.Name == "httputil" &&
|
||||||
|
(selectorName == "HandleError" || selectorName == "WriteError" || selectorName == "WriteJson" || selectorName == "WriteSSZ") {
|
||||||
|
return call, selectorName
|
||||||
}
|
}
|
||||||
return nil
|
return nil, ""
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user