From 691a44cecb76ffeaa53b4ecc694c7b931c466fd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Sat, 5 Jun 2021 22:17:53 +0100 Subject: [PATCH] avoid breaking const declarations using iotas With the -literals flag, we try to convert some const declarations to vars, as long as that doesn't break typechecking. We really only do that for typed constant strings, really. There was a quirk: if a numerical constant had a type and used iota, we would not obfuscate its value, but we would still convert the declaration from const to var. Since iotas only work within const declarations, that would break compilation: > garble -literals build [stderr] # test/main FeWE3zwi.go:19: undefined: iota exit status 2 To fix the problem, make the logic more conservative: only obfuscate constant declarations where the values are typed strings, meaning that any numerical constants are left entirely untouched. This fixes the build of google.golang.org/protobuf/runtime/protoiface with -literals turned on. --- internal/literals/literals.go | 10 ++-------- testdata/scripts/literals.txt | 5 +++++ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/internal/literals/literals.go b/internal/literals/literals.go index 9ed5bdc..8f3b722 100644 --- a/internal/literals/literals.go +++ b/internal/literals/literals.go @@ -51,14 +51,8 @@ func Obfuscate(file *ast.File, info *types.Info, fset *token.FileSet, ignoreObj for _, name := range spec.Names { obj := info.ObjectOf(name) - basic, ok := obj.Type().(*types.Basic) - if !ok { - // skip the block if it contains non basic types - return false - } - - if basic.Info()&types.IsUntyped != 0 { - // skip the block if it contains untyped constants + // We only obfuscate const declarations with typed string values. + if obj.Type() != types.Typ[types.String] { return false } diff --git a/testdata/scripts/literals.txt b/testdata/scripts/literals.txt index fcc3b08..97dc18d 100644 --- a/testdata/scripts/literals.txt +++ b/testdata/scripts/literals.txt @@ -88,6 +88,11 @@ const ( skip2 = "also skip this" ) +// We used to conver this to a var in an attempt of obfuscating the literal. +// That would break the iota, which only works inside const declarations. +// We only obfuscate constant declarations with string values, anyway. +const fooTyped uint64 = 1 << iota + const arrayLen = 4 var array [arrayLen]byte