diff --git a/analyzer/testdata/src/filtertest/f1.go b/analyzer/testdata/src/filtertest/f1.go index ca562347..a64ed7c5 100644 --- a/analyzer/testdata/src/filtertest/f1.go +++ b/analyzer/testdata/src/filtertest/f1.go @@ -576,6 +576,51 @@ func detectHasMethod() { } } +func detectSameTypeSizes() { + { + typeTest(int8(1), int8(2), "same type sizes") // want `true` + typeTest(float64(1), float64(2.5), "same type sizes") // want `true` + typeTest(float32(1), float64(2), "same type sizes") + } + + { + var s string + var b []byte + typeTest(s, s, "same type sizes") // want `true` + typeTest(b, b, "same type sizes") // want `true` + typeTest(s, b, "same type sizes") + } + + { + var a10 [10]byte + var a15 [15]byte + typeTest(a10, a10, "same type sizes") // want `true` + typeTest(a15, a15, "same type sizes") // want `true` + typeTest(a15[:], a15[:], "same type sizes") // want `true` + typeTest(a10[:], a15[:], "same type sizes") // want `true` + typeTest(a15[:], a10[:], "same type sizes") // want `true` + typeTest(a15, a10, "same type sizes") + typeTest(a10, a15, "same type sizes") + } + + { + type vector2 struct { + x, y float64 + } + type vector3 struct { + x, y, z float64 + } + var a, b vector2 + typeTest(a, b, "same type sizes") // want `true` + typeTest(vector2{}, vector2{}, "same type sizes") // want `true` + typeTest(vector3{}, vector3{}, "same type sizes") // want `true` + typeTest(vector2{}, vector3{}, "same type sizes") + typeTest(vector3{}, vector2{}, "same type sizes") + typeTest(vector2{}, 14, "same type sizes") + typeTest(14, vector2{}, "same type sizes") + } +} + func detectAddressable(x int, xs []int) { typeTest("variadic addressable") // want `true` typeTest(x, "variadic addressable") // want `true` diff --git a/analyzer/testdata/src/filtertest/rules.go b/analyzer/testdata/src/filtertest/rules.go index bd81bbbf..4bbd70c0 100644 --- a/analyzer/testdata/src/filtertest/rules.go +++ b/analyzer/testdata/src/filtertest/rules.go @@ -247,4 +247,8 @@ func testRules(m dsl.Matcher) { m.Match(`typeTest($x, "has String method")`). Where(m["x"].Type.HasMethod(`fmt.Stringer.String`)). Report(`true`) + + m.Match(`typeTest($x, $y, "same type sizes")`). + Where(m["x"].Type.Size == m["y"].Type.Size). + Report(`true`) } diff --git a/ruleguard/filters.go b/ruleguard/filters.go index 61b0758b..713caaf4 100644 --- a/ruleguard/filters.go +++ b/ruleguard/filters.go @@ -375,6 +375,19 @@ func makeTypeSizeConstFilter(src, varname string, op token.Token, rhsValue const } } +func makeTypeSizeFilter(src, varname string, op token.Token, rhsVarname string) filterFunc { + return func(params *filterParams) matchFilterResult { + lhsTyp := params.typeofNode(params.subExpr(varname)) + lhsValue := constant.MakeInt64(params.ctx.Sizes.Sizeof(lhsTyp)) + rhsTyp := params.typeofNode(params.subExpr(rhsVarname)) + rhsValue := constant.MakeInt64(params.ctx.Sizes.Sizeof(rhsTyp)) + if constant.Compare(lhsValue, op, rhsValue) { + return filterSuccess + } + return filterFailure(src) + } +} + func makeValueIntConstFilter(src, varname string, op token.Token, rhsValue constant.Value) filterFunc { return func(params *filterParams) matchFilterResult { if list, ok := params.subNode(varname).(gogrep.ExprSlice); ok { diff --git a/ruleguard/ir_loader.go b/ruleguard/ir_loader.go index 823274bd..fbdf06cd 100644 --- a/ruleguard/ir_loader.go +++ b/ruleguard/ir_loader.go @@ -813,6 +813,8 @@ func (l *irLoader) newBinaryExprFilter(filter ir.FilterExpr, info *filterInfo) ( case ir.FilterVarTypeSizeOp: if rhsValue != nil { result.fn = makeTypeSizeConstFilter(result.src, lhs.Value.(string), tok, rhsValue) + } else { + result.fn = makeTypeSizeFilter(result.src, lhs.Value.(string), tok, rhs.Value.(string)) } case ir.FilterVarValueIntOp: if rhsValue != nil {