示例#1
0
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))
		}
	}
}
示例#2
0
// describePointer runs the pointer analysis of the selected SSA value.
func describePointer(o *Oracle, v ssa.Value, indirect bool) (ptrs []pointerResult, err error) {
	buildSSA(o)

	// TODO(adonovan): don't run indirect pointer analysis on non-ptr-ptrlike types.
	o.config.Queries = map[ssa.Value]pointer.Indirect{v: pointer.Indirect(indirect)}
	ptares := ptrAnalysis(o)

	// Combine the PT sets from all contexts.
	pointers := ptares.Queries[v]
	if pointers == nil {
		return nil, fmt.Errorf("PTA did not encounter this expression (dead code?)")
	}
	pts := pointer.PointsToCombined(pointers)

	if pointer.CanHaveDynamicTypes(v.Type()) {
		// Show concrete types for interface/reflect.Value expression.
		if concs := pts.DynamicTypes(); concs.Len() > 0 {
			concs.Iterate(func(conc types.Type, pta interface{}) {
				combined := pointer.PointsToCombined(pta.([]pointer.Pointer))
				labels := combined.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{v.Type(), labels})
	}
	sort.Sort(byTypeString(ptrs)) // to ensure determinism
	return ptrs, nil
}
示例#3
0
// 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)

	if isAddr {
		o.ptaConfig.AddIndirectQuery(v)
	} else {
		o.ptaConfig.AddQuery(v)
	}
	ptares := ptrAnalysis(o)

	// Combine the PT sets from all contexts.
	var pointers []pointer.Pointer
	if isAddr {
		pointers = ptares.IndirectQueries[v]
	} else {
		pointers = ptares.Queries[v]
	}
	if pointers == nil {
		return nil, fmt.Errorf("pointer analysis did not find expression (dead code?)")
	}
	pts := pointer.PointsToCombined(pointers)

	if pointer.CanHaveDynamicTypes(v.Type()) {
		// Show concrete types for interface/reflect.Value expression.
		if concs := pts.DynamicTypes(); concs.Len() > 0 {
			concs.Iterate(func(conc types.Type, pta interface{}) {
				combined := pointer.PointsToCombined(pta.([]pointer.Pointer))
				labels := combined.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{v.Type(), labels})
	}
	sort.Sort(byTypeString(ptrs)) // to ensure determinism
	return ptrs, nil
}
func checkTypesExpectation(e *expectation, pr *probe) bool {
	var expected typemap.M
	var surplus typemap.M
	exact := true
	for _, g := range e.types {
		if g == types.Typ[types.Invalid] {
			exact = false
			continue
		}
		expected.Set(g, struct{}{})
	}

	if t := pr.instr.Args[0].Type(); !pointer.CanHaveDynamicTypes(t) {
		e.errorf("@types expectation requires an interface- or reflect.Value-typed operand, got %s", t)
		return false
	}

	// Find the set of types that the probe's
	// argument (x in print(x)) may contain.
	for _, T := range pr.arg0.PointsTo().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
}
示例#5
0
func (r *describeValueResult) display(printf printfFunc) {
	var prefix, suffix string
	if r.constVal != nil {
		suffix = fmt.Sprintf(" of constant value %s", r.constVal)
	}
	switch obj := r.obj.(type) {
	case *types.Func:
		if recv := obj.Type().(*types.Signature).Recv(); recv != nil {
			if _, ok := recv.Type().Underlying().(*types.Interface); ok {
				prefix = "interface method "
			} else {
				prefix = "method "
			}
		}

	case *types.Var:
		// TODO(adonovan): go/types should make it simple to
		// ask: IsStructField(*Var)?
		if false {
			prefix = "struct field "
		}
	}

	// Describe the expression.
	if r.obj != nil {
		if r.obj.Pos() == r.expr.Pos() {
			// defining ident
			printf(r.expr, "definition of %s%s%s", prefix, r.obj, suffix)
		} else {
			// referring ident
			printf(r.expr, "reference to %s%s%s", prefix, r.obj, suffix)
			if def := r.obj.Pos(); def != token.NoPos {
				printf(def, "defined here")
			}
		}
	} else {
		desc := importer.NodeDescription(r.expr)
		if suffix != "" {
			// constant expression
			printf(r.expr, "%s%s", desc, suffix)
		} else {
			// non-constant expression
			printf(r.expr, "%s of type %s", desc, r.typ)
		}
	}

	// pointer analysis could not be run
	if r.ptaErr != nil {
		printf(r.expr, "no points-to information: %s", r.ptaErr)
		return
	}

	if r.ptrs == nil {
		return // PTA was not invoked (not an error)
	}

	// Display the results of pointer analysis.
	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.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:", ptr.typ)
					printLabels(printf, ptr.labels, "\t\t")
				} else {
					printf(obj, "\t%s", 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, "value may point to these labels:")
			printLabels(printf, ptr.labels, "\t")
		} else {
			printf(r.qpos, "value cannot point to anything.")
		}
	}
}