diff options
author | Than McIntosh <thanm@google.com> | 2021-02-19 10:09:15 -0500 |
---|---|---|
committer | Dmitri Shuralyov <dmitshur@golang.org> | 2021-03-01 20:13:56 +0000 |
commit | 18e5d75ffb3c8d2be8c92f801aded70321e0b84b (patch) | |
tree | bd911dfa9ed76fd9ea057e6c8ed2bc96f9f38cd1 | |
parent | ddeae6b248e5130fe634047c3ca5964f5fa4e3dd (diff) | |
download | go-18e5d75ffb3c8d2be8c92f801aded70321e0b84b.tar.gz go-18e5d75ffb3c8d2be8c92f801aded70321e0b84b.zip |
[release-branch.go1.16] cmd/compile: fix panic in DWARF-gen handling obfuscated code
DWARF generation uses variable source positions (file/line/col) as a
way to uniquely identify locals and parameters, as part of the process
of matching up post-optimization variables with the corresponding
pre-optimization versions (since the DWARF needs to be in terms of the
original source constructs).
This strategy can run into problems when compiling obfuscated or
machine-generated code, where you can in some circumstances wind up
with two local variables that appear to have the same name, file,
line, and column. This patch changes DWARF generation to skip over
such duplicates as opposed to issuing a fatal error (if an
obfuscation tool is in use, it is unlikely that a human being will be
able to make much sense of DWARF info in any case).
Fixes #44433.
Change-Id: I198022d184701aa9ec3dce42c005d29b72d2e321
Reviewed-on: https://go-review.googlesource.com/c/go/+/294289
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Trust: Than McIntosh <thanm@google.com>
Run-TryBot: Than McIntosh <thanm@google.com>
(cherry picked from commit e78e04ce39b9df316edda08f43f253f5e9ac509e)
Reviewed-on: https://go-review.googlesource.com/c/go/+/294789
-rw-r--r-- | src/cmd/compile/internal/gc/dwinl.go | 3 | ||||
-rw-r--r-- | test/fixedbugs/issue44378.go | 40 |
2 files changed, 42 insertions, 1 deletions
diff --git a/src/cmd/compile/internal/gc/dwinl.go b/src/cmd/compile/internal/gc/dwinl.go index bb5ae61cbb..31d076814c 100644 --- a/src/cmd/compile/internal/gc/dwinl.go +++ b/src/cmd/compile/internal/gc/dwinl.go @@ -243,7 +243,8 @@ func makePreinlineDclMap(fnsym *obj.LSym) map[varPos]int { DeclCol: pos.Col(), } if _, found := m[vp]; found { - Fatalf("child dcl collision on symbol %s within %v\n", n.Sym.Name, fnsym.Name) + // We can see collisions (variables with the same name/file/line/col) in obfuscated or machine-generated code -- see issue 44378 for an example. Skip duplicates in such cases, since it is unlikely that a human will be debugging such code. + continue } m[vp] = i } diff --git a/test/fixedbugs/issue44378.go b/test/fixedbugs/issue44378.go new file mode 100644 index 0000000000..58c88d573f --- /dev/null +++ b/test/fixedbugs/issue44378.go @@ -0,0 +1,40 @@ +// compile + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This test case caused a panic in the compiler's DWARF gen code. + +// Note to future maintainers of this code: +// +// ** Do NOT run gofmt when editing this file ** +// +// In order for the buggy behavior to be triggered in the compiler, +// we need to have a the function of interest all on one gigantic line. + +package a + +type O interface{} +type IO int +type OS int + +type A struct { + x int +} + +// original versions of the two function +func (p *A) UO(o O) { + p.r(o, o) +} +func (p *A) r(o1, o2 O) { + switch x := o1.(type) { + case *IO: + p.x = int(*x) + case *OS: + p.x = int(*x + 2) + } +} + +// see note above about the importance of all this code winding up on one line. +var myverylongname0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 int ; func (p *A) UO2(o O) { p.r2(o, o); }; func (p *A) r2(o1, o2 O) { switch x := o1.(type) { case *IO: p.x = int(*x); case *OS: p.x = int(*x + 2); } } |