diff options
Diffstat (limited to 'meta/recipes-devtools/go/go-1.14/CVE-2023-24538_4.patch')
-rw-r--r-- | meta/recipes-devtools/go/go-1.14/CVE-2023-24538_4.patch | 497 |
1 files changed, 497 insertions, 0 deletions
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-24538_4.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-24538_4.patch new file mode 100644 index 0000000000..d5e2eb6684 --- /dev/null +++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-24538_4.patch @@ -0,0 +1,497 @@ +From 760d88497091fb5d6d231a18e6f4e06ecb9af9b2 Mon Sep 17 00:00:00 2001 +From: Russ Cox <rsc@golang.org> +Date: Thu, 10 Sep 2020 18:53:26 -0400 +Subject: [PATCH 4/6] text/template: allow newlines inside action delimiters + +This allows multiline constructs like: + + {{"hello" | + printf}} + +Now that unclosed actions can span multiple lines, +track and report the start of the action when reporting errors. + +Also clean up a few "unexpected <error message>" to be just "<error message>". + +Fixes #29770. + +Change-Id: I54c6c016029a8328b7902a4b6d85eab713ec3285 +Reviewed-on: https://go-review.googlesource.com/c/go/+/254257 +Trust: Russ Cox <rsc@golang.org> +Run-TryBot: Russ Cox <rsc@golang.org> +TryBot-Result: Go Bot <gobot@golang.org> +Reviewed-by: Rob Pike <r@golang.org> + +Dependency Patch #4 + +Upstream-Status: Backport from https://github.com/golang/go/commit/9384d34c58099657bb1b133beaf3ff37ada9b017 +CVE: CVE-2023-24538 +Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com> +--- + src/text/template/doc.go | 21 ++++----- + src/text/template/exec_test.go | 2 +- + src/text/template/parse/lex.go | 84 +++++++++++++++++------------------ + src/text/template/parse/lex_test.go | 2 +- + src/text/template/parse/parse.go | 59 +++++++++++++----------- + src/text/template/parse/parse_test.go | 36 ++++++++++++--- + 6 files changed, 117 insertions(+), 87 deletions(-) + +diff --git a/src/text/template/doc.go b/src/text/template/doc.go +index 4b0efd2..7b30294 100644 +--- a/src/text/template/doc.go ++++ b/src/text/template/doc.go +@@ -40,16 +40,17 @@ More intricate examples appear below. + Text and spaces + + By default, all text between actions is copied verbatim when the template is +-executed. For example, the string " items are made of " in the example above appears +-on standard output when the program is run. +- +-However, to aid in formatting template source code, if an action's left delimiter +-(by default "{{") is followed immediately by a minus sign and ASCII space character +-("{{- "), all trailing white space is trimmed from the immediately preceding text. +-Similarly, if the right delimiter ("}}") is preceded by a space and minus sign +-(" -}}"), all leading white space is trimmed from the immediately following text. +-In these trim markers, the ASCII space must be present; "{{-3}}" parses as an +-action containing the number -3. ++executed. For example, the string " items are made of " in the example above ++appears on standard output when the program is run. ++ ++However, to aid in formatting template source code, if an action's left ++delimiter (by default "{{") is followed immediately by a minus sign and white ++space, all trailing white space is trimmed from the immediately preceding text. ++Similarly, if the right delimiter ("}}") is preceded by white space and a minus ++sign, all leading white space is trimmed from the immediately following text. ++In these trim markers, the white space must be present: ++"{{- 3}}" is like "{{3}}" but trims the immediately preceding text, while ++"{{-3}}" parses as an action containing the number -3. + + For instance, when executing the template whose source is + +diff --git a/src/text/template/exec_test.go b/src/text/template/exec_test.go +index b8a809e..3309b33 100644 +--- a/src/text/template/exec_test.go ++++ b/src/text/template/exec_test.go +@@ -1295,7 +1295,7 @@ func TestUnterminatedStringError(t *testing.T) { + t.Fatal("expected error") + } + str := err.Error() +- if !strings.Contains(str, "X:3: unexpected unterminated raw quoted string") { ++ if !strings.Contains(str, "X:3: unterminated raw quoted string") { + t.Fatalf("unexpected error: %s", str) + } + } +diff --git a/src/text/template/parse/lex.go b/src/text/template/parse/lex.go +index e41373a..6784071 100644 +--- a/src/text/template/parse/lex.go ++++ b/src/text/template/parse/lex.go +@@ -92,15 +92,14 @@ const eof = -1 + // If the action begins "{{- " rather than "{{", then all space/tab/newlines + // preceding the action are trimmed; conversely if it ends " -}}" the + // leading spaces are trimmed. This is done entirely in the lexer; the +-// parser never sees it happen. We require an ASCII space to be +-// present to avoid ambiguity with things like "{{-3}}". It reads ++// parser never sees it happen. We require an ASCII space (' ', \t, \r, \n) ++// to be present to avoid ambiguity with things like "{{-3}}". It reads + // better with the space present anyway. For simplicity, only ASCII +-// space does the job. ++// does the job. + const ( +- spaceChars = " \t\r\n" // These are the space characters defined by Go itself. +- leftTrimMarker = "- " // Attached to left delimiter, trims trailing spaces from preceding text. +- rightTrimMarker = " -" // Attached to right delimiter, trims leading spaces from following text. +- trimMarkerLen = Pos(len(leftTrimMarker)) ++ spaceChars = " \t\r\n" // These are the space characters defined by Go itself. ++ trimMarker = '-' // Attached to left/right delimiter, trims trailing spaces from preceding/following text. ++ trimMarkerLen = Pos(1 + 1) // marker plus space before or after + ) + + // stateFn represents the state of the scanner as a function that returns the next state. +@@ -108,19 +107,18 @@ type stateFn func(*lexer) stateFn + + // lexer holds the state of the scanner. + type lexer struct { +- name string // the name of the input; used only for error reports +- input string // the string being scanned +- leftDelim string // start of action +- rightDelim string // end of action +- trimRightDelim string // end of action with trim marker +- emitComment bool // emit itemComment tokens. +- pos Pos // current position in the input +- start Pos // start position of this item +- width Pos // width of last rune read from input +- items chan item // channel of scanned items +- parenDepth int // nesting depth of ( ) exprs +- line int // 1+number of newlines seen +- startLine int // start line of this item ++ name string // the name of the input; used only for error reports ++ input string // the string being scanned ++ leftDelim string // start of action ++ rightDelim string // end of action ++ emitComment bool // emit itemComment tokens. ++ pos Pos // current position in the input ++ start Pos // start position of this item ++ width Pos // width of last rune read from input ++ items chan item // channel of scanned items ++ parenDepth int // nesting depth of ( ) exprs ++ line int // 1+number of newlines seen ++ startLine int // start line of this item + } + + // next returns the next rune in the input. +@@ -213,15 +211,14 @@ func lex(name, input, left, right string, emitComment bool) *lexer { + right = rightDelim + } + l := &lexer{ +- name: name, +- input: input, +- leftDelim: left, +- rightDelim: right, +- trimRightDelim: rightTrimMarker + right, +- emitComment: emitComment, +- items: make(chan item), +- line: 1, +- startLine: 1, ++ name: name, ++ input: input, ++ leftDelim: left, ++ rightDelim: right, ++ emitComment: emitComment, ++ items: make(chan item), ++ line: 1, ++ startLine: 1, + } + go l.run() + return l +@@ -251,7 +248,7 @@ func lexText(l *lexer) stateFn { + ldn := Pos(len(l.leftDelim)) + l.pos += Pos(x) + trimLength := Pos(0) +- if strings.HasPrefix(l.input[l.pos+ldn:], leftTrimMarker) { ++ if hasLeftTrimMarker(l.input[l.pos+ldn:]) { + trimLength = rightTrimLength(l.input[l.start:l.pos]) + } + l.pos -= trimLength +@@ -280,7 +277,7 @@ func rightTrimLength(s string) Pos { + + // atRightDelim reports whether the lexer is at a right delimiter, possibly preceded by a trim marker. + func (l *lexer) atRightDelim() (delim, trimSpaces bool) { +- if strings.HasPrefix(l.input[l.pos:], l.trimRightDelim) { // With trim marker. ++ if hasRightTrimMarker(l.input[l.pos:]) && strings.HasPrefix(l.input[l.pos+trimMarkerLen:], l.rightDelim) { // With trim marker. + return true, true + } + if strings.HasPrefix(l.input[l.pos:], l.rightDelim) { // Without trim marker. +@@ -297,7 +294,7 @@ func leftTrimLength(s string) Pos { + // lexLeftDelim scans the left delimiter, which is known to be present, possibly with a trim marker. + func lexLeftDelim(l *lexer) stateFn { + l.pos += Pos(len(l.leftDelim)) +- trimSpace := strings.HasPrefix(l.input[l.pos:], leftTrimMarker) ++ trimSpace := hasLeftTrimMarker(l.input[l.pos:]) + afterMarker := Pos(0) + if trimSpace { + afterMarker = trimMarkerLen +@@ -342,7 +339,7 @@ func lexComment(l *lexer) stateFn { + + // lexRightDelim scans the right delimiter, which is known to be present, possibly with a trim marker. + func lexRightDelim(l *lexer) stateFn { +- trimSpace := strings.HasPrefix(l.input[l.pos:], rightTrimMarker) ++ trimSpace := hasRightTrimMarker(l.input[l.pos:]) + if trimSpace { + l.pos += trimMarkerLen + l.ignore() +@@ -369,7 +366,7 @@ func lexInsideAction(l *lexer) stateFn { + return l.errorf("unclosed left paren") + } + switch r := l.next(); { +- case r == eof || isEndOfLine(r): ++ case r == eof: + return l.errorf("unclosed action") + case isSpace(r): + l.backup() // Put space back in case we have " -}}". +@@ -439,7 +436,7 @@ func lexSpace(l *lexer) stateFn { + } + // Be careful about a trim-marked closing delimiter, which has a minus + // after a space. We know there is a space, so check for the '-' that might follow. +- if strings.HasPrefix(l.input[l.pos-1:], l.trimRightDelim) { ++ if hasRightTrimMarker(l.input[l.pos-1:]) && strings.HasPrefix(l.input[l.pos-1+trimMarkerLen:], l.rightDelim) { + l.backup() // Before the space. + if numSpaces == 1 { + return lexRightDelim // On the delim, so go right to that. +@@ -526,7 +523,7 @@ func lexFieldOrVariable(l *lexer, typ itemType) stateFn { + // day to implement arithmetic. + func (l *lexer) atTerminator() bool { + r := l.peek() +- if isSpace(r) || isEndOfLine(r) { ++ if isSpace(r) { + return true + } + switch r { +@@ -657,15 +654,18 @@ Loop: + + // isSpace reports whether r is a space character. + func isSpace(r rune) bool { +- return r == ' ' || r == '\t' +-} +- +-// isEndOfLine reports whether r is an end-of-line character. +-func isEndOfLine(r rune) bool { +- return r == '\r' || r == '\n' ++ return r == ' ' || r == '\t' || r == '\r' || r == '\n' + } + + // isAlphaNumeric reports whether r is an alphabetic, digit, or underscore. + func isAlphaNumeric(r rune) bool { + return r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r) + } ++ ++func hasLeftTrimMarker(s string) bool { ++ return len(s) >= 2 && s[0] == trimMarker && isSpace(rune(s[1])) ++} ++ ++func hasRightTrimMarker(s string) bool { ++ return len(s) >= 2 && isSpace(rune(s[0])) && s[1] == trimMarker ++} +diff --git a/src/text/template/parse/lex_test.go b/src/text/template/parse/lex_test.go +index f6d5f28..6510eed 100644 +--- a/src/text/template/parse/lex_test.go ++++ b/src/text/template/parse/lex_test.go +@@ -323,7 +323,7 @@ var lexTests = []lexTest{ + tLeft, + mkItem(itemError, "unrecognized character in action: U+0001"), + }}, +- {"unclosed action", "{{\n}}", []item{ ++ {"unclosed action", "{{", []item{ + tLeft, + mkItem(itemError, "unclosed action"), + }}, +diff --git a/src/text/template/parse/parse.go b/src/text/template/parse/parse.go +index 496d8bf..5e6e512 100644 +--- a/src/text/template/parse/parse.go ++++ b/src/text/template/parse/parse.go +@@ -24,13 +24,14 @@ type Tree struct { + Mode Mode // parsing mode. + text string // text parsed to create the template (or its parent) + // Parsing only; cleared after parse. +- funcs []map[string]interface{} +- lex *lexer +- token [3]item // three-token lookahead for parser. +- peekCount int +- vars []string // variables defined at the moment. +- treeSet map[string]*Tree +- mode Mode ++ funcs []map[string]interface{} ++ lex *lexer ++ token [3]item // three-token lookahead for parser. ++ peekCount int ++ vars []string // variables defined at the moment. ++ treeSet map[string]*Tree ++ actionLine int // line of left delim starting action ++ mode Mode + } + + // A mode value is a set of flags (or 0). Modes control parser behavior. +@@ -187,6 +188,16 @@ func (t *Tree) expectOneOf(expected1, expected2 itemType, context string) item { + + // unexpected complains about the token and terminates processing. + func (t *Tree) unexpected(token item, context string) { ++ if token.typ == itemError { ++ extra := "" ++ if t.actionLine != 0 && t.actionLine != token.line { ++ extra = fmt.Sprintf(" in action started at %s:%d", t.ParseName, t.actionLine) ++ if strings.HasSuffix(token.val, " action") { ++ extra = extra[len(" in action"):] // avoid "action in action" ++ } ++ } ++ t.errorf("%s%s", token, extra) ++ } + t.errorf("unexpected %s in %s", token, context) + } + +@@ -350,6 +361,8 @@ func (t *Tree) textOrAction() Node { + case itemText: + return t.newText(token.pos, token.val) + case itemLeftDelim: ++ t.actionLine = token.line ++ defer t.clearActionLine() + return t.action() + case itemComment: + return t.newComment(token.pos, token.val) +@@ -359,6 +372,10 @@ func (t *Tree) textOrAction() Node { + return nil + } + ++func (t *Tree) clearActionLine() { ++ t.actionLine = 0 ++} ++ + // Action: + // control + // command ("|" command)* +@@ -384,12 +401,12 @@ func (t *Tree) action() (n Node) { + t.backup() + token := t.peek() + // Do not pop variables; they persist until "end". +- return t.newAction(token.pos, token.line, t.pipeline("command")) ++ return t.newAction(token.pos, token.line, t.pipeline("command", itemRightDelim)) + } + + // Pipeline: + // declarations? command ('|' command)* +-func (t *Tree) pipeline(context string) (pipe *PipeNode) { ++func (t *Tree) pipeline(context string, end itemType) (pipe *PipeNode) { + token := t.peekNonSpace() + pipe = t.newPipeline(token.pos, token.line, nil) + // Are there declarations or assignments? +@@ -430,12 +447,9 @@ decls: + } + for { + switch token := t.nextNonSpace(); token.typ { +- case itemRightDelim, itemRightParen: ++ case end: + // At this point, the pipeline is complete + t.checkPipeline(pipe, context) +- if token.typ == itemRightParen { +- t.backup() +- } + return + case itemBool, itemCharConstant, itemComplex, itemDot, itemField, itemIdentifier, + itemNumber, itemNil, itemRawString, itemString, itemVariable, itemLeftParen: +@@ -464,7 +478,7 @@ func (t *Tree) checkPipeline(pipe *PipeNode, context string) { + + func (t *Tree) parseControl(allowElseIf bool, context string) (pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) { + defer t.popVars(len(t.vars)) +- pipe = t.pipeline(context) ++ pipe = t.pipeline(context, itemRightDelim) + var next Node + list, next = t.itemList() + switch next.Type() { +@@ -550,7 +564,7 @@ func (t *Tree) blockControl() Node { + + token := t.nextNonSpace() + name := t.parseTemplateName(token, context) +- pipe := t.pipeline(context) ++ pipe := t.pipeline(context, itemRightDelim) + + block := New(name) // name will be updated once we know it. + block.text = t.text +@@ -580,7 +594,7 @@ func (t *Tree) templateControl() Node { + if t.nextNonSpace().typ != itemRightDelim { + t.backup() + // Do not pop variables; they persist until "end". +- pipe = t.pipeline(context) ++ pipe = t.pipeline(context, itemRightDelim) + } + return t.newTemplate(token.pos, token.line, name, pipe) + } +@@ -614,13 +628,12 @@ func (t *Tree) command() *CommandNode { + switch token := t.next(); token.typ { + case itemSpace: + continue +- case itemError: +- t.errorf("%s", token.val) + case itemRightDelim, itemRightParen: + t.backup() + case itemPipe: ++ // nothing here; break loop below + default: +- t.errorf("unexpected %s in operand", token) ++ t.unexpected(token, "operand") + } + break + } +@@ -675,8 +688,6 @@ func (t *Tree) operand() Node { + // A nil return means the next item is not a term. + func (t *Tree) term() Node { + switch token := t.nextNonSpace(); token.typ { +- case itemError: +- t.errorf("%s", token.val) + case itemIdentifier: + if !t.hasFunction(token.val) { + t.errorf("function %q not defined", token.val) +@@ -699,11 +710,7 @@ func (t *Tree) term() Node { + } + return number + case itemLeftParen: +- pipe := t.pipeline("parenthesized pipeline") +- if token := t.next(); token.typ != itemRightParen { +- t.errorf("unclosed right paren: unexpected %s", token) +- } +- return pipe ++ return t.pipeline("parenthesized pipeline", itemRightParen) + case itemString, itemRawString: + s, err := strconv.Unquote(token.val) + if err != nil { +diff --git a/src/text/template/parse/parse_test.go b/src/text/template/parse/parse_test.go +index d9c13c5..220f984 100644 +--- a/src/text/template/parse/parse_test.go ++++ b/src/text/template/parse/parse_test.go +@@ -250,6 +250,13 @@ var parseTests = []parseTest{ + {"comment trim left and right", "x \r\n\t{{- /* */ -}}\n\n\ty", noError, `"x""y"`}, + {"block definition", `{{block "foo" .}}hello{{end}}`, noError, + `{{template "foo" .}}`}, ++ ++ {"newline in assignment", "{{ $x \n := \n 1 \n }}", noError, "{{$x := 1}}"}, ++ {"newline in empty action", "{{\n}}", hasError, "{{\n}}"}, ++ {"newline in pipeline", "{{\n\"x\"\n|\nprintf\n}}", noError, `{{"x" | printf}}`}, ++ {"newline in comment", "{{/*\nhello\n*/}}", noError, ""}, ++ {"newline in comment", "{{-\n/*\nhello\n*/\n-}}", noError, ""}, ++ + // Errors. + {"unclosed action", "hello{{range", hasError, ""}, + {"unmatched end", "{{end}}", hasError, ""}, +@@ -426,23 +433,38 @@ var errorTests = []parseTest{ + // Check line numbers are accurate. + {"unclosed1", + "line1\n{{", +- hasError, `unclosed1:2: unexpected unclosed action in command`}, ++ hasError, `unclosed1:2: unclosed action`}, + {"unclosed2", + "line1\n{{define `x`}}line2\n{{", +- hasError, `unclosed2:3: unexpected unclosed action in command`}, ++ hasError, `unclosed2:3: unclosed action`}, ++ {"unclosed3", ++ "line1\n{{\"x\"\n\"y\"\n", ++ hasError, `unclosed3:4: unclosed action started at unclosed3:2`}, ++ {"unclosed4", ++ "{{\n\n\n\n\n", ++ hasError, `unclosed4:6: unclosed action started at unclosed4:1`}, ++ {"var1", ++ "line1\n{{\nx\n}}", ++ hasError, `var1:3: function "x" not defined`}, + // Specific errors. + {"function", + "{{foo}}", + hasError, `function "foo" not defined`}, +- {"comment", ++ {"comment1", + "{{/*}}", +- hasError, `unclosed comment`}, ++ hasError, `comment1:1: unclosed comment`}, ++ {"comment2", ++ "{{/*\nhello\n}}", ++ hasError, `comment2:1: unclosed comment`}, + {"lparen", + "{{.X (1 2 3}}", + hasError, `unclosed left paren`}, + {"rparen", +- "{{.X 1 2 3)}}", +- hasError, `unexpected ")"`}, ++ "{{.X 1 2 3 ) }}", ++ hasError, `unexpected ")" in command`}, ++ {"rparen2", ++ "{{(.X 1 2 3", ++ hasError, `unclosed action`}, + {"space", + "{{`x`3}}", + hasError, `in operand`}, +@@ -488,7 +510,7 @@ var errorTests = []parseTest{ + hasError, `missing value for parenthesized pipeline`}, + {"multilinerawstring", + "{{ $v := `\n` }} {{", +- hasError, `multilinerawstring:2: unexpected unclosed action`}, ++ hasError, `multilinerawstring:2: unclosed action`}, + {"rangeundefvar", + "{{range $k}}{{end}}", + hasError, `undefined variable`}, +-- +2.7.4 |