go cmd/vet: false positive printf detection for URL-encoded / (%2F) in string literal

8wtpewkr  于 10个月前  发布在  Go
关注(0)|答案(6)|浏览(104)

你正在使用的Go版本是什么( go version )?

  1. $ go version
  2. go version go1.11 darwin/amd64

这个问题在最新版本的发布中是否重现?

是的

你正在使用什么操作系统和处理器架构( go env )?

go env 输出

  1. $ go env
  2. GOARCH="amd64"
  3. GOBIN=""
  4. GOCACHE="/Users/msl21dp/Library/Caches/go-build"
  5. GOEXE=""
  6. GOFLAGS=""
  7. GOHOSTARCH="amd64"
  8. GOHOSTOS="darwin"
  9. GOOS="darwin"
  10. GOPATH="/Users/msl21dp/go"
  11. GOPROXY=""
  12. GORACE=""
  13. GOROOT="/Users/msl21dp/.gvm/gos/go1.11"
  14. GOTMPDIR=""
  15. GOTOOLDIR="/Users/msl21dp/.gvm/gos/go1.11/pkg/tool/darwin_amd64"
  16. GCCGO="gccgo"
  17. CC="clang"
  18. CXX="clang++"
  19. CGO_ENABLED="1"
  20. GOMOD="/Users/msl21dp/gomod/homedepot.com/vulcancore/go.mod"
  21. CGO_CFLAGS="-g -O2"
  22. CGO_CPPFLAGS=""
  23. CGO_CXXFLAGS="-g -O2"
  24. CGO_FFLAGS="-g -O2"
  25. CGO_LDFLAGS="-g -O2"
  26. PKG_CONFIG="pkg-config"
  27. GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/4y/g8py5x0x0rx2qxlpxls23gnw0000gn/T/go-build585874623=/tmp/go-build -gno-record-gcc-switches -fno-common"

你做了什么?

使用日志库github.com/spf13/jwalterweatherman,我们的日志中有这样一行:

  1. logging.INFO.Println("Logs can be viewed at https://console.cloud.google.com/logs/viewer?project=redacted&logName=projects%2Fredacted%2Flogs%redacted")

这应该在控制台打印一个用户可以点击的URL。由于URL包含一个作为参数的斜杠分隔的字符串,这些斜杠必须进行URL编码,对于正则表达式来说,这是 %2F

你期望看到什么?

没有验证错误

你看到了什么?

vet触发了一个错误:

  1. Logger.Println call has possible formatting directive %2F

通常情况下这不是问题,但从Go 1.10开始,现在原生运行 go test ,并使用硬编码的检查列表,唯一的选择是将此转换为Printf并将百分号加倍以转义它们,或者在 go test 期间禁用 go vet ,这两种方法都不是很好的解决方案。

建议/可能的解决方案:

  • 找出如何过滤这种情况。在这种情况下,可能的格式化指令是A)大写,以及B)在没有参数的Print调用中使用该指令(这意味着我不得不不正确地在非 f 调用中使用格式化指令,并且忘记在格式化字符串中包含要替换它的值)。
  • 让特定的测试在 go test 自动运行 go vet 时被禁用,可能通过类似 -vetflags="-printf=false" 这样的标志来实现。这也将允许任何其他针对vet的特定标志传递给它。
5n0oy7gb

5n0oy7gb1#

真正的问题是为什么vet认为Println是一个printf Package 器,而实际上它并不是。如果它确实是一个printf Package 器,那么报告将是正确的,你应该使用%%2F来转义%

v440hwme

v440hwme2#

我认为这更像是在指出,这个print调用可能是有意将其编码为Println的,但无意中被错误地编码为Println,导致指令被忽略,任何参数都被简单地附加。这是一个合理且相当有用的检查。只是在使用Println打印URL编码的字符时,它会模仿实际的格式指令时才会失效。

mm5n2pyu

mm5n2pyu3#

当然,你是对的。

vmpqdwk3

vmpqdwk34#

也许我们可以教分类器忽略某些常见的误报,比如 %2F 对于 / ,%3F 对于 ? ,%3D 对于 = 等等。只要我们将这些限制在字母上,我认为我们不应该担心添加误报。
@alandonovan@josharian 有什么想法?

gajydyqb

gajydyqb5#

是的,检查%XX(不以零开头的大写十六进制)可能是你提到的所有URL编码情况的最简单的解决方法。当然,仍然会有偶尔的误报。

anhgbhbe

anhgbhbe6#

我认为它不应该对只有一个参数的调用进行标记。不太可能有人不小心使用了Println而不是Printf,并且忘记为格式动词提供参数。

相关问题