From d108f21846cb7392c43bd40817d484f877c1b53f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Fri, 2 Jun 2023 23:03:36 +0100 Subject: [PATCH] apply TODO to rename "cannot obfuscate" APIs They have been exclusively about reflect for over a year now. Make that clearer, and update the docs as well. --- main.go | 15 +++++++++------ reflect.go | 45 ++++++++++++++++++++------------------------- 2 files changed, 29 insertions(+), 31 deletions(-) diff --git a/main.go b/main.go index 84ea18f..17030d0 100644 --- a/main.go +++ b/main.go @@ -1272,11 +1272,14 @@ type pkgCache struct { // unless we were smart enough to detect which arguments get used as %#v or %T. ReflectAPIs map[funcFullName]map[int]bool - // CannotObfuscate is filled with the fully qualified names from each - // package that we cannot obfuscate. + // ReflectObjects is filled with the fully qualified names from each + // package that we cannot obfuscate due to reflection. + // The included objects are named types and their fields, + // since it is those names being obfuscated that could break the use of reflect. + // // This record is necessary for knowing what names from imported packages // weren't obfuscated, so we can obfuscate their local uses accordingly. - CannotObfuscate map[objectString]struct{} + ReflectObjects map[objectString]struct{} // EmbeddedAliasFields records which embedded fields use a type alias. // They are the only instance where a type alias matters for obfuscation, @@ -1292,7 +1295,7 @@ var curPkgCache = pkgCache{ "reflect.TypeOf": {0: true}, "reflect.ValueOf": {0: true}, }, - CannotObfuscate: map[objectString]struct{}{}, + ReflectObjects: map[objectString]struct{}{}, EmbeddedAliasFields: map[objectString]typeName{}, } @@ -1797,7 +1800,7 @@ func (tf *transformer) transformGoFile(file *ast.File) *ast.File { // and it's entirely unsupported, but try to accomodate for now. // At least it's enough to leave the rtype and Value types intact. case "rtype", "Value": - tf.recursivelyRecordAsNotObfuscated(obj.Type()) + tf.recursivelyRecordUsedForReflect(obj.Type()) return true } case "crypto/x509/pkix": @@ -1812,7 +1815,7 @@ func (tf *transformer) transformGoFile(file *ast.File) *ast.File { } // The package that declared this object did not obfuscate it. - if recordedAsNotObfuscated(obj) { + if usedForReflect(obj) { return true } diff --git a/reflect.go b/reflect.go index 08dfbe6..0c542c5 100644 --- a/reflect.go +++ b/reflect.go @@ -114,7 +114,7 @@ func (tf *transformer) checkMethodSignature(reflectParams map[int]bool, sig *typ if ignore { reflectParams[i] = true - tf.recursivelyRecordAsNotObfuscated(param.Type()) + tf.recursivelyRecordUsedForReflect(param.Type()) } } } @@ -245,7 +245,7 @@ func (tf *transformer) recordArgReflected(val ssa.Value, visited map[ssa.Value]b case *ssa.Alloc: /* fmt.Printf("recording val %v \n", *val.Referrers()) */ - tf.recursivelyRecordAsNotObfuscated(val.Type()) + tf.recursivelyRecordUsedForReflect(val.Type()) for _, ref := range *val.Referrers() { if idx, ok := ref.(*ssa.IndexAddr); ok { @@ -260,9 +260,9 @@ func (tf *transformer) recordArgReflected(val ssa.Value, visited map[ssa.Value]b return relatedParam(val, visited) case *ssa.Const: - tf.recursivelyRecordAsNotObfuscated(val.Type()) + tf.recursivelyRecordUsedForReflect(val.Type()) case *ssa.Global: - tf.recursivelyRecordAsNotObfuscated(val.Type()) + tf.recursivelyRecordUsedForReflect(val.Type()) // TODO: this might need similar logic to *ssa.Alloc, however // reassigning a function param to a global variable and then reflecting @@ -271,7 +271,7 @@ func (tf *transformer) recordArgReflected(val ssa.Value, visited map[ssa.Value]b // this only finds the parameters who want to be found, // otherwise relatedParam is used for more in depth analysis - tf.recursivelyRecordAsNotObfuscated(val.Type()) + tf.recursivelyRecordUsedForReflect(val.Type()) return val } @@ -341,13 +341,13 @@ func relatedParam(val ssa.Value, visited map[ssa.Value]bool) *ssa.Parameter { return nil } -// recursivelyRecordAsNotObfuscated calls recordAsNotObfuscated on any named +// recursivelyRecordUsedForReflect calls recordUsedForReflect on any named // types and fields under typ. // // Only the names declared in the current package are recorded. This is to ensure // that reflection detection only happens within the package declaring a type. // Detecting it in downstream packages could result in inconsistencies. -func (tf *transformer) recursivelyRecordAsNotObfuscated(t types.Type) { +func (tf *transformer) recursivelyRecordUsedForReflect(t types.Type) { switch t := t.(type) { case *types.Named: obj := t.Obj() @@ -357,13 +357,13 @@ func (tf *transformer) recursivelyRecordAsNotObfuscated(t types.Type) { if obj.Pkg() == nil || obj.Pkg() != tf.pkg { return // not from the specified package } - if recordedAsNotObfuscated(obj) { + if usedForReflect(obj) { return // prevent endless recursion } - recordAsNotObfuscated(obj) + recordUsedForReflect(obj) // Record the underlying type, too. - tf.recursivelyRecordAsNotObfuscated(t.Underlying()) + tf.recursivelyRecordUsedForReflect(t.Underlying()) case *types.Struct: for i := 0; i < t.NumFields(); i++ { @@ -377,14 +377,14 @@ func (tf *transformer) recursivelyRecordAsNotObfuscated(t types.Type) { } // Record the field itself, too. - recordAsNotObfuscated(field) + recordUsedForReflect(field) - tf.recursivelyRecordAsNotObfuscated(field.Type()) + tf.recursivelyRecordUsedForReflect(field.Type()) } case interface{ Elem() types.Type }: // Get past pointers, slices, etc. - tf.recursivelyRecordAsNotObfuscated(t.Elem()) + tf.recursivelyRecordUsedForReflect(t.Elem()) } } @@ -421,16 +421,11 @@ func recordedObjectString(obj types.Object) objectString { return pkg.Path() + "." + obj.Name() } -// recordAsNotObfuscated records all the objects whose names we cannot obfuscate. -// An object is any named entity, such as a declared variable or type. -// -// As of June 2022, this only records types which are used in reflection. -// TODO(mvdan): If this is still the case in a year's time, -// we should probably rename "not obfuscated" and "cannot obfuscate" to be -// directly about reflection, e.g. "used in reflection". -func recordAsNotObfuscated(obj types.Object) { +// recordUsedForReflect records the objects whose names we cannot obfuscate due to reflection. +// We currently record named types and fields. +func recordUsedForReflect(obj types.Object) { if obj.Pkg().Path() != curPkg.ImportPath { - panic("called recordedAsNotObfuscated with a foreign object") + panic("called recordUsedForReflect with a foreign object") } objStr := recordedObjectString(obj) if objStr == "" { @@ -438,14 +433,14 @@ func recordAsNotObfuscated(obj types.Object) { // do we need to record it at all? return } - curPkgCache.CannotObfuscate[objStr] = struct{}{} + curPkgCache.ReflectObjects[objStr] = struct{}{} } -func recordedAsNotObfuscated(obj types.Object) bool { +func usedForReflect(obj types.Object) bool { objStr := recordedObjectString(obj) if objStr == "" { return false } - _, ok := curPkgCache.CannotObfuscate[objStr] + _, ok := curPkgCache.ReflectObjects[objStr] return ok }