From c59c3f4fa11aafd880926e4077e033d9f04c5671 Mon Sep 17 00:00:00 2001 From: Yuxin Wang Date: Fri, 4 Oct 2024 17:06:44 -0400 Subject: [PATCH] Generalize trusted function framework to be a hook framework (#278) This PR generalizes the trusted function framework to be a NilAway-wide hook framework. To be honest it was already a NilAway-wide thing: it hooks into different parts of the system and can do different actions based on certain conditions. This PR simply lifts it up to the root level and call it "hook" instead of trusted function: in the future we may leverage this framework to handle more than function calls, with more types of actions, and hooking into more points (e.g., even in inference). This PR is the first of a series of PRs to generalize this framework: this one simply does the relocation with no changes other than reference updates. --- assertion/function/assertiontree/backprop_util.go | 4 ++-- .../function/assertiontree/parse_expr_producer.go | 4 ++-- assertion/function/preprocess/cfg.go | 4 ++-- .../trustedfunc/trustedfunc.go => hook/hook.go | 12 +++++------- 4 files changed, 11 insertions(+), 13 deletions(-) rename assertion/function/trustedfunc/trustedfunc.go => hook/hook.go (97%) diff --git a/assertion/function/assertiontree/backprop_util.go b/assertion/function/assertiontree/backprop_util.go index 01afa882..cd7dee1f 100644 --- a/assertion/function/assertiontree/backprop_util.go +++ b/assertion/function/assertiontree/backprop_util.go @@ -23,7 +23,7 @@ import ( "go/types" "go.uber.org/nilaway/annotation" - "go.uber.org/nilaway/assertion/function/trustedfunc" + "go.uber.org/nilaway/hook" "go.uber.org/nilaway/util" "go.uber.org/nilaway/util/asthelper" "golang.org/x/tools/go/analysis" @@ -245,7 +245,7 @@ func isErrorReturnNil(rootNode *RootAssertionNode, errRet ast.Expr) bool { // isErrorReturnNonnil returns true if the error return is guaranteed to be nonnil, false otherwise func isErrorReturnNonnil(rootNode *RootAssertionNode, errRet ast.Expr) bool { t := rootNode.Pass().TypesInfo.TypeOf(errRet) - if _, ok := trustedfunc.As(errRet, rootNode.Pass()); ok || util.TypeAsDeeplyStruct(t) != nil { + if _, ok := hook.As(errRet, rootNode.Pass()); ok || util.TypeAsDeeplyStruct(t) != nil { return true } diff --git a/assertion/function/assertiontree/parse_expr_producer.go b/assertion/function/assertiontree/parse_expr_producer.go index c55cabf9..1b354805 100644 --- a/assertion/function/assertiontree/parse_expr_producer.go +++ b/assertion/function/assertiontree/parse_expr_producer.go @@ -21,7 +21,7 @@ import ( "go.uber.org/nilaway/annotation" "go.uber.org/nilaway/assertion/function/producer" - "go.uber.org/nilaway/assertion/function/trustedfunc" + "go.uber.org/nilaway/hook" "go.uber.org/nilaway/util" ) @@ -240,7 +240,7 @@ func (r *RootAssertionNode) ParseExprAsProducer(expr ast.Expr, doNotTrack bool) return true } - if ret, ok := trustedfunc.As(expr, r.Pass()); ok { + if ret, ok := hook.As(expr, r.Pass()); ok { if prod, ok := ret.(*annotation.ProduceTrigger); ok { return nil, []producer.ParsedProducer{producer.ShallowParsedProducer{Producer: prod}} } diff --git a/assertion/function/preprocess/cfg.go b/assertion/function/preprocess/cfg.go index d8a99c38..404cd32d 100644 --- a/assertion/function/preprocess/cfg.go +++ b/assertion/function/preprocess/cfg.go @@ -19,7 +19,7 @@ import ( "go/ast" "go/token" - "go.uber.org/nilaway/assertion/function/trustedfunc" + "go.uber.org/nilaway/hook" "go.uber.org/nilaway/util" "golang.org/x/tools/go/cfg" ) @@ -133,7 +133,7 @@ func (p *Preprocessor) splitBlockOnTrustedFuncs(graph *cfg.CFG, thisBlock, failu if call, ok = expr.X.(*ast.CallExpr); !ok { continue } - if retExpr, ok = trustedfunc.As(call, p.pass); !ok { + if retExpr, ok = hook.As(call, p.pass); !ok { continue } if trustedCond, ok = retExpr.(ast.Expr); !ok { diff --git a/assertion/function/trustedfunc/trustedfunc.go b/hook/hook.go similarity index 97% rename from assertion/function/trustedfunc/trustedfunc.go rename to hook/hook.go index ce299ac9..8848aab5 100644 --- a/assertion/function/trustedfunc/trustedfunc.go +++ b/hook/hook.go @@ -12,11 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package trustedfunc implements a trusted function framework where it hooks into different parts -// of NilAway to provide additional context for certain function calls. This is useful for -// well-known standard or 3rd party libraries where we can encode certain knowledge about them ( -// e.g., `assert.Nil(t, x)` implies `x == nil`) and use that to provide better analysis. -package trustedfunc +// Package hook implements a hook framework for NilAway where it hooks into different parts to +// provide additional context for certain function calls. This is useful for well-known standard +// or 3rd party libraries where we can encode certain knowledge about them (e.g., +// `assert.Nil(t, x)` implies `x == nil`) and use that to provide better analysis. +package hook import ( "go/ast" @@ -30,8 +30,6 @@ import ( "golang.org/x/tools/go/analysis" ) -// NOTE: in the future, when we implement to add contracts, this trusted func mechanism can possibly be replaced with that one. - // As checks a function call AST node to see if it is one of the trusted functions, and if it is // then runs the corresponding action and returns that as the output along with a bool indicating // success or failure. For example, a binary expression `x != nil` is returned for trusted function