mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Handle cross-package global guards.
Updates #7721 PiperOrigin-RevId: 455029306
This commit is contained in:
committed by
gVisor bot
parent
c54948f3c1
commit
1ff543e17e
@@ -322,9 +322,17 @@ func (pc *passContext) checkFieldAccess(inst almostInst, structObj ssa.Value, fi
|
||||
pc.checkGuards(inst, structObj, fieldObj, ls, isWrite)
|
||||
}
|
||||
|
||||
// noReferrers wraps an instruction as an almostInst.
|
||||
type noReferrers struct {
|
||||
ssa.Instruction
|
||||
}
|
||||
|
||||
// Referrers implements almostInst.Referrers.
|
||||
func (noReferrers) Referrers() *[]ssa.Instruction { return nil }
|
||||
|
||||
// checkGlobalAccess checks the validity of a global access.
|
||||
func (pc *passContext) checkGlobalAccess(g *ssa.Global, ls *lockState, isWrite bool) {
|
||||
pc.checkGuards(g, g, g.Object(), ls, isWrite)
|
||||
func (pc *passContext) checkGlobalAccess(inst ssa.Instruction, g *ssa.Global, ls *lockState, isWrite bool) {
|
||||
pc.checkGuards(noReferrers{inst}, g, g.Object(), ls, isWrite)
|
||||
}
|
||||
|
||||
func (pc *passContext) checkCall(call callCommon, lff *lockFunctionFacts, ls *lockState) {
|
||||
@@ -592,7 +600,7 @@ func (pc *passContext) checkInstruction(inst ssa.Instruction, lff *lockFunctionF
|
||||
continue
|
||||
}
|
||||
_, isWrite := inst.(*ssa.Store)
|
||||
pc.checkGlobalAccess(g, ls, isWrite)
|
||||
pc.checkGlobalAccess(inst, g, ls, isWrite)
|
||||
}
|
||||
|
||||
// Process the instruction.
|
||||
|
||||
@@ -167,6 +167,9 @@ type globalGuard struct {
|
||||
// ObjectName indicates the object from which resolution should occur.
|
||||
ObjectName string
|
||||
|
||||
// PackageName is the package where the object lives.
|
||||
PackageName string
|
||||
|
||||
// FieldList is the traversal path from object.
|
||||
FieldList fieldList
|
||||
}
|
||||
@@ -179,7 +182,11 @@ type ssaPackager interface {
|
||||
// resolveCommon implements resolution for all cases.
|
||||
func (g *globalGuard) resolveCommon(pc *passContext, ls *lockState) resolvedValue {
|
||||
state := pc.pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA)
|
||||
v := state.Pkg.Members[g.ObjectName].(ssa.Value)
|
||||
pkg := state.Pkg
|
||||
if g.PackageName != "" && g.PackageName != state.Pkg.Pkg.Path() {
|
||||
pkg = state.Pkg.Prog.ImportedPackage(g.PackageName)
|
||||
}
|
||||
v := pkg.Members[g.ObjectName].(ssa.Value)
|
||||
return makeResolvedValue(v, g.FieldList)
|
||||
}
|
||||
|
||||
@@ -627,8 +634,9 @@ func (pc *passContext) findGlobalGuard(pos token.Pos, guardName string) (*global
|
||||
return nil, false
|
||||
}
|
||||
return &globalGuard{
|
||||
ObjectName: parts[0],
|
||||
FieldList: fl,
|
||||
ObjectName: parts[0],
|
||||
PackageName: pc.pass.Pkg.Path(),
|
||||
FieldList: fl,
|
||||
}, true
|
||||
}
|
||||
|
||||
|
||||
@@ -27,4 +27,5 @@ go_library(
|
||||
# control expected failures for analysis.
|
||||
marshal = False,
|
||||
stateify = False,
|
||||
deps = ["//tools/checklocks/test/crosspkg"],
|
||||
)
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
load("//tools:defs.bzl", "go_library")
|
||||
|
||||
package(licenses = ["notice"])
|
||||
|
||||
go_library(
|
||||
name = "crosspkg",
|
||||
srcs = ["crosspkg.go"],
|
||||
# See next level up.
|
||||
marshal = False,
|
||||
stateify = False,
|
||||
visibility = ["//tools/checklocks/test:__pkg__"],
|
||||
)
|
||||
@@ -0,0 +1,26 @@
|
||||
// Copyright 2022 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package crosspkg is a second package for testing.
|
||||
package crosspkg
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
// +checklocks:FooMu
|
||||
Foo int
|
||||
FooMu sync.Mutex
|
||||
)
|
||||
@@ -16,6 +16,8 @@ package test
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"gvisor.dev/gvisor/tools/checklocks/test/crosspkg"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -83,3 +85,13 @@ func testGlobalInvalid() {
|
||||
otherStruct.guardedField2 = 1 // +checklocksfail
|
||||
otherStruct.guardedField3 = 1 // +checklocksfail
|
||||
}
|
||||
|
||||
func testCrosspkgGlobalValid() {
|
||||
crosspkg.FooMu.Lock()
|
||||
crosspkg.Foo = 1
|
||||
crosspkg.FooMu.Unlock()
|
||||
}
|
||||
|
||||
func testCrosspkgGlobalInvalid() {
|
||||
crosspkg.Foo = 1 // +checklocksfail
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user