func (r *pointstoResult) display(printf printfFunc) { if pointer.CanHaveDynamicTypes(r.typ) { // Show concrete types for interface, reflect.Type or // reflect.Value expression. if len(r.ptrs) > 0 { printf(r.qpos, "this %s may contain these dynamic types:", r.qpos.typeString(r.typ)) for _, ptr := range r.ptrs { var obj types.Object if nt, ok := deref(ptr.typ).(*types.Named); ok { obj = nt.Obj() } if len(ptr.labels) > 0 { printf(obj, "\t%s, may point to:", r.qpos.typeString(ptr.typ)) printLabels(printf, ptr.labels, "\t\t") } else { printf(obj, "\t%s", r.qpos.typeString(ptr.typ)) } } } else { printf(r.qpos, "this %s cannot contain any dynamic types.", r.typ) } } else { // Show labels for other expressions. if ptr := r.ptrs[0]; len(ptr.labels) > 0 { printf(r.qpos, "this %s may point to these objects:", r.qpos.typeString(r.typ)) printLabels(printf, ptr.labels, "\t") } else { printf(r.qpos, "this %s may not point to anything.", r.qpos.typeString(r.typ)) } } }
// runPTA runs the pointer analysis of the selected SSA value or address. func runPTA(o *Oracle, v ssa.Value, isAddr bool) (ptrs []pointerResult, err error) { buildSSA(o) T := v.Type() if isAddr { o.ptaConfig.AddIndirectQuery(v) T = deref(T) } else { o.ptaConfig.AddQuery(v) } ptares := ptrAnalysis(o) var ptr pointer.Pointer if isAddr { ptr = ptares.IndirectQueries[v] } else { ptr = ptares.Queries[v] } if ptr == (pointer.Pointer{}) { return nil, fmt.Errorf("pointer analysis did not find expression (dead code?)") } pts := ptr.PointsTo() if pointer.CanHaveDynamicTypes(T) { // Show concrete types for interface/reflect.Value expression. if concs := pts.DynamicTypes(); concs.Len() > 0 { concs.Iterate(func(conc types.Type, pta interface{}) { labels := pta.(pointer.PointsToSet).Labels() sort.Sort(byPosAndString(labels)) // to ensure determinism ptrs = append(ptrs, pointerResult{conc, labels}) }) } } else { // Show labels for other expressions. labels := pts.Labels() sort.Sort(byPosAndString(labels)) // to ensure determinism ptrs = append(ptrs, pointerResult{T, labels}) } sort.Sort(byTypeString(ptrs)) // to ensure determinism return ptrs, nil }
func checkTypesExpectation(e *expectation, pts pointer.PointsToSet, typ types.Type) bool { var expected typeutil.Map var surplus typeutil.Map exact := true for _, g := range e.types { if g == types.Typ[types.Invalid] { exact = false continue } expected.Set(g, struct{}{}) } if !pointer.CanHaveDynamicTypes(typ) { e.errorf("@types expectation requires an interface- or reflect.Value-typed operand, got %s", typ) return false } // Find the set of types that the probe's // argument (x in print(x)) may contain. for _, T := range pts.DynamicTypes().Keys() { if expected.At(T) != nil { expected.Delete(T) } else if exact { surplus.Set(T, struct{}{}) } } // Report set difference: ok := true if expected.Len() > 0 { ok = false e.errorf("interface cannot contain these types: %s", expected.KeysString()) } if surplus.Len() > 0 { ok = false e.errorf("interface may additionally contain these types: %s", surplus.KeysString()) } return ok }