diff --git a/go/analysis/passes/printf/testdata/src/a/a.go b/go/analysis/passes/printf/testdata/src/a/a.go index 40e8f2f77c..603179bccb 100644 --- a/go/analysis/passes/printf/testdata/src/a/a.go +++ b/go/analysis/passes/printf/testdata/src/a/a.go @@ -237,7 +237,7 @@ func PrintfTests() { Printf("%T", someFunction) // ok: maybe someone wants to see the type // Bug: used to recur forever. Printf("%p %x", recursiveStructV, recursiveStructV.next) - Printf("%p %x", recursiveStruct1V, recursiveStruct1V.next) + Printf("%p %x", recursiveStruct1V, recursiveStruct1V.next) // want `Printf format %x has arg recursiveStruct1V\.next of wrong type \*a\.RecursiveStruct2` Printf("%p %x", recursiveSliceV, recursiveSliceV) Printf("%p %x", recursiveMapV, recursiveMapV) // Special handling for Log. @@ -678,6 +678,14 @@ func PointersToCompoundTypes() { intMap := map[int]int{3: 4} fmt.Printf("%s", &intMap) // want `Printf format %s has arg &intMap of wrong type \*map\[int\]int` + + type T2 struct { + X string + } + type T1 struct { + X *T2 + } + fmt.Printf("%s\n", T1{&T2{"x"}}) // want `Printf format %s has arg T1{&T2{.x.}} of wrong type a\.T1` } // Printf wrappers from external package diff --git a/go/analysis/passes/printf/types.go b/go/analysis/passes/printf/types.go index 28d94e1f94..0ebc8107f3 100644 --- a/go/analysis/passes/printf/types.go +++ b/go/analysis/passes/printf/types.go @@ -108,9 +108,13 @@ func matchArgTypeInternal(pass *analysis.Pass, t printfArgType, typ types.Type, // Check whether the rest can print pointers. return t&argPointer != 0 } - // If it's a pointer to a struct, array, slice, or map, that's - // equivalent in our analysis to whether we can print the type - // being pointed to. + // If it's a top-level pointer to a struct, array, slice, or + // map, that's equivalent in our analysis to whether we can + // print the type being pointed to. Pointers in nested levels + // are not supported to minimize fmt running into loops. + if len(inProgress) > 1 { + return false + } return matchArgTypeInternal(pass, t, under, arg, inProgress) case *types.Struct: