mirror of
https://github.com/golang/go
synced 2024-09-28 17:24:28 -06:00
go/printer: error out of Fprint when it would write a '//line' directive with a multiline file path
Line directives do not provide a way to escape newline characters, so source file paths containing newlines must not be written in them. Updates #60167. Change-Id: I30f8b381cc7d1df6914c27591544edf424a4b634 Reviewed-on: https://go-review.googlesource.com/c/go/+/501578 Reviewed-by: Robert Griesemer <gri@google.com> Auto-Submit: Bryan Mills <bcmills@google.com> Run-TryBot: Bryan Mills <bcmills@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
8bfe839c5f
commit
b9baf4452f
@ -75,10 +75,11 @@ type printer struct {
|
||||
// white space). If there's a difference and SourcePos is set in
|
||||
// ConfigMode, //line directives are used in the output to restore
|
||||
// original source positions for a reader.
|
||||
pos token.Position // current position in AST (source) space
|
||||
out token.Position // current position in output space
|
||||
last token.Position // value of pos after calling writeString
|
||||
linePtr *int // if set, record out.Line for the next token in *linePtr
|
||||
pos token.Position // current position in AST (source) space
|
||||
out token.Position // current position in output space
|
||||
last token.Position // value of pos after calling writeString
|
||||
linePtr *int // if set, record out.Line for the next token in *linePtr
|
||||
sourcePosErr error // if non-nil, the first error emitting a //line directive
|
||||
|
||||
// The list of all source comments, in order of appearance.
|
||||
comments []*ast.CommentGroup // may be nil
|
||||
@ -196,6 +197,13 @@ func (p *printer) lineFor(pos token.Pos) int {
|
||||
// writeLineDirective writes a //line directive if necessary.
|
||||
func (p *printer) writeLineDirective(pos token.Position) {
|
||||
if pos.IsValid() && (p.out.Line != pos.Line || p.out.Filename != pos.Filename) {
|
||||
if strings.ContainsAny(pos.Filename, "\r\n") {
|
||||
if p.sourcePosErr == nil {
|
||||
p.sourcePosErr = fmt.Errorf("go/printer: source filename contains unexpected newline character: %q", pos.Filename)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
p.output = append(p.output, tabwriter.Escape) // protect '\n' in //line from tabwriter interpretation
|
||||
p.output = append(p.output, fmt.Sprintf("//line %s:%d\n", pos.Filename, pos.Line)...)
|
||||
p.output = append(p.output, tabwriter.Escape)
|
||||
@ -1169,7 +1177,7 @@ func (p *printer) printNode(node any) error {
|
||||
goto unsupported
|
||||
}
|
||||
|
||||
return nil
|
||||
return p.sourcePosErr
|
||||
|
||||
unsupported:
|
||||
return fmt.Errorf("go/printer: unsupported node type %T", node)
|
||||
|
@ -797,3 +797,31 @@ func f() {
|
||||
t.Fatalf("got %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSourcePosNewline(t *testing.T) {
|
||||
// We don't provide a syntax for escaping or unescaping characters in line
|
||||
// directives (see https://go.dev/issue/24183#issuecomment-372449628).
|
||||
// As a result, we cannot write a line directive with the correct path for a
|
||||
// filename containing newlines. We should return an error rather than
|
||||
// silently dropping or mangling it.
|
||||
|
||||
fname := "foo\nbar/bar.go"
|
||||
src := `package bar`
|
||||
fset := token.NewFileSet()
|
||||
f, err := parser.ParseFile(fset, fname, src, parser.ParseComments|parser.AllErrors|parser.SkipObjectResolution)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cfg := &Config{
|
||||
Mode: SourcePos, // emit line comments
|
||||
Tabwidth: 8,
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
if err := cfg.Fprint(&buf, fset, f); err == nil {
|
||||
t.Errorf("Fprint did not error for source file path containing newline")
|
||||
}
|
||||
if buf.Len() != 0 {
|
||||
t.Errorf("unexpected Fprint output:\n%s", buf.Bytes())
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user