summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/go/go-1.14/CVE-2023-39318.patch
blob: 00def8fcda9e6f4e09d06d3af0a46faff963babd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
From 023b542edf38e2a1f87fcefb9f75ff2f99401b4c Mon Sep 17 00:00:00 2001
From: Roland Shoemaker <bracewell@google.com>
Date: Thu, 3 Aug 2023 12:24:13 -0700
Subject: [PATCH] [release-branch.go1.20] html/template: support HTML-like
 comments in script contexts

Per Appendix B.1.1 of the ECMAScript specification, support HTML-like
comments in script contexts. Also per section 12.5, support hashbang
comments. This brings our parsing in-line with how browsers treat these
comment types.

Thanks to Takeshi Kaneko (GMO Cybersecurity by Ierae, Inc.) for
reporting this issue.

Fixes #62196
Fixes #62395
Fixes CVE-2023-39318

Change-Id: Id512702c5de3ae46cf648e268cb10e1eb392a181
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1976593
Run-TryBot: Roland Shoemaker <bracewell@google.com>
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2014620
Reviewed-on: https://go-review.googlesource.com/c/go/+/526098
Run-TryBot: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>

Upstream-Status: Backport from [https://github.com/golang/go/commit/023b542edf38e2a1f87fcefb9f75ff2f99401b4c]
CVE: CVE-2023-39318
Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
---
 src/html/template/context.go      |  6 ++-
 src/html/template/escape.go       |  5 +-
 src/html/template/escape_test.go  | 10 ++++
 src/html/template/state_string.go | 26 +++++-----
 src/html/template/transition.go   | 80 ++++++++++++++++++++-----------
 5 files changed, 84 insertions(+), 43 deletions(-)

diff --git a/src/html/template/context.go b/src/html/template/context.go
index 0b65313..4eb7891 100644
--- a/src/html/template/context.go
+++ b/src/html/template/context.go
@@ -124,6 +124,10 @@ const (
 	stateJSBlockCmt
 	// stateJSLineCmt occurs inside a JavaScript // line comment.
 	stateJSLineCmt
+	// stateJSHTMLOpenCmt occurs inside a JavaScript <!-- HTML-like comment.
+	stateJSHTMLOpenCmt
+	// stateJSHTMLCloseCmt occurs inside a JavaScript --> HTML-like comment.
+	stateJSHTMLCloseCmt
 	// stateCSS occurs inside a <style> element or style attribute.
 	stateCSS
 	// stateCSSDqStr occurs inside a CSS double quoted string.
@@ -149,7 +153,7 @@ const (
 // authors & maintainers, not for end-users or machines.
 func isComment(s state) bool {
 	switch s {
-	case stateHTMLCmt, stateJSBlockCmt, stateJSLineCmt, stateCSSBlockCmt, stateCSSLineCmt:
+	case stateHTMLCmt, stateJSBlockCmt, stateJSLineCmt, stateJSHTMLOpenCmt, stateJSHTMLCloseCmt, stateCSSBlockCmt, stateCSSLineCmt:
 		return true
 	}
 	return false
diff --git a/src/html/template/escape.go b/src/html/template/escape.go
index 435f912..ad2ec69 100644
--- a/src/html/template/escape.go
+++ b/src/html/template/escape.go
@@ -698,9 +698,12 @@ func (e *escaper) escapeText(c context, n *parse.TextNode) context {
 		if c.state != c1.state && isComment(c1.state) && c1.delim == delimNone {
 			// Preserve the portion between written and the comment start.
 			cs := i1 - 2
-			if c1.state == stateHTMLCmt {
+			if c1.state == stateHTMLCmt || c1.state == stateJSHTMLOpenCmt {
 				// "<!--" instead of "/*" or "//"
 				cs -= 2
+			} else if c1.state == stateJSHTMLCloseCmt {
+				// "-->" instead of "/*" or "//"
+				cs -= 1
 			}
 			b.Write(s[written:cs])
 			written = i1
diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go
index f550691..5f41e52 100644
--- a/src/html/template/escape_test.go
+++ b/src/html/template/escape_test.go
@@ -503,6 +503,16 @@ func TestEscape(t *testing.T) {
 			"<script>var a/*b*///c\nd</script>",
 			"<script>var a \nd</script>",
 		},
+		{
+			"JS HTML-like comments",
+			"<script>before <!-- beep\nbetween\nbefore-->boop\n</script>",
+			"<script>before \nbetween\nbefore\n</script>",
+		},
+		{
+			"JS hashbang comment",
+			"<script>#! beep\n</script>",
+			"<script>\n</script>",
+		},
 		{
 			"CSS comments",
 			"<style>p// paragraph\n" +
diff --git a/src/html/template/state_string.go b/src/html/template/state_string.go
index 05104be..b5cfe70 100644
--- a/src/html/template/state_string.go
+++ b/src/html/template/state_string.go
@@ -25,21 +25,23 @@ func _() {
 	_ = x[stateJSRegexp-14]
 	_ = x[stateJSBlockCmt-15]
 	_ = x[stateJSLineCmt-16]
-	_ = x[stateCSS-17]
-	_ = x[stateCSSDqStr-18]
-	_ = x[stateCSSSqStr-19]
-	_ = x[stateCSSDqURL-20]
-	_ = x[stateCSSSqURL-21]
-	_ = x[stateCSSURL-22]
-	_ = x[stateCSSBlockCmt-23]
-	_ = x[stateCSSLineCmt-24]
-	_ = x[stateError-25]
-	_ = x[stateDead-26]
+	_ = x[stateJSHTMLOpenCmt-17]
+	_ = x[stateJSHTMLCloseCmt-18]
+	_ = x[stateCSS-19]
+	_ = x[stateCSSDqStr-20]
+	_ = x[stateCSSSqStr-21]
+	_ = x[stateCSSDqURL-22]
+	_ = x[stateCSSSqURL-23]
+	_ = x[stateCSSURL-24]
+	_ = x[stateCSSBlockCmt-25]
+	_ = x[stateCSSLineCmt-26]
+	_ = x[stateError-27]
+	_ = x[stateDead-28]
 }
 
-const _state_name = "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSBqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateErrorstateDead"
+const _state_name = "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSBqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateJSHTMLOpenCmtstateJSHTMLCloseCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateErrorstateDead"
 
-var _state_index = [...]uint16{0, 9, 17, 30, 44, 60, 72, 83, 92, 100, 111, 118, 130, 142, 154, 167, 182, 196, 204, 217, 230, 243, 256, 267, 283, 298, 308, 317}
+var _state_index = [...]uint16{0, 9, 17, 30, 44, 60, 72, 83, 92, 100, 111, 118, 130, 142, 154, 167, 182, 196, 214, 233, 241, 254, 267, 280, 293, 304, 320, 335, 345, 354}
 
 func (i state) String() string {
 	if i >= state(len(_state_index)-1) {
diff --git a/src/html/template/transition.go b/src/html/template/transition.go
index 92eb351..12aa4c4 100644
--- a/src/html/template/transition.go
+++ b/src/html/template/transition.go
@@ -14,32 +14,34 @@ import (
 // the updated context and the number of bytes consumed from the front of the
 // input.
 var transitionFunc = [...]func(context, []byte) (context, int){
-	stateText:        tText,
-	stateTag:         tTag,
-	stateAttrName:    tAttrName,
-	stateAfterName:   tAfterName,
-	stateBeforeValue: tBeforeValue,
-	stateHTMLCmt:     tHTMLCmt,
-	stateRCDATA:      tSpecialTagEnd,
-	stateAttr:        tAttr,
-	stateURL:         tURL,
-	stateSrcset:      tURL,
-	stateJS:          tJS,
-	stateJSDqStr:     tJSDelimited,
-	stateJSSqStr:     tJSDelimited,
-	stateJSBqStr:     tJSDelimited,
-	stateJSRegexp:    tJSDelimited,
-	stateJSBlockCmt:  tBlockCmt,
-	stateJSLineCmt:   tLineCmt,
-	stateCSS:         tCSS,
-	stateCSSDqStr:    tCSSStr,
-	stateCSSSqStr:    tCSSStr,
-	stateCSSDqURL:    tCSSStr,
-	stateCSSSqURL:    tCSSStr,
-	stateCSSURL:      tCSSStr,
-	stateCSSBlockCmt: tBlockCmt,
-	stateCSSLineCmt:  tLineCmt,
-	stateError:       tError,
+	stateText:           tText,
+	stateTag:            tTag,
+	stateAttrName:       tAttrName,
+	stateAfterName:      tAfterName,
+	stateBeforeValue:    tBeforeValue,
+	stateHTMLCmt:        tHTMLCmt,
+	stateRCDATA:         tSpecialTagEnd,
+	stateAttr:           tAttr,
+	stateURL:            tURL,
+	stateSrcset:         tURL,
+	stateJS:             tJS,
+	stateJSDqStr:        tJSDelimited,
+	stateJSSqStr:        tJSDelimited,
+	stateJSBqStr:        tJSDelimited,
+	stateJSRegexp:       tJSDelimited,
+	stateJSBlockCmt:     tBlockCmt,
+	stateJSLineCmt:      tLineCmt,
+	stateJSHTMLOpenCmt:  tLineCmt,
+	stateJSHTMLCloseCmt: tLineCmt,
+	stateCSS:            tCSS,
+	stateCSSDqStr:       tCSSStr,
+	stateCSSSqStr:       tCSSStr,
+	stateCSSDqURL:       tCSSStr,
+	stateCSSSqURL:       tCSSStr,
+	stateCSSURL:         tCSSStr,
+	stateCSSBlockCmt:    tBlockCmt,
+	stateCSSLineCmt:     tLineCmt,
+	stateError:          tError,
 }
 
 var commentStart = []byte("<!--")
@@ -263,7 +265,7 @@ func tURL(c context, s []byte) (context, int) {
 
 // tJS is the context transition function for the JS state.
 func tJS(c context, s []byte) (context, int) {
-	i := bytes.IndexAny(s, "\"`'/")
+	i := bytes.IndexAny(s, "\"`'/<-#")
 	if i == -1 {
 		// Entire input is non string, comment, regexp tokens.
 		c.jsCtx = nextJSCtx(s, c.jsCtx)
@@ -293,6 +295,26 @@ func tJS(c context, s []byte) (context, int) {
 				err:   errorf(ErrSlashAmbig, nil, 0, "'/' could start a division or regexp: %.32q", s[i:]),
 			}, len(s)
 		}
+	// ECMAScript supports HTML style comments for legacy reasons, see Appendix
+	// B.1.1 "HTML-like Comments". The handling of these comments is somewhat
+	// confusing. Multi-line comments are not supported, i.e. anything on lines
+	// between the opening and closing tokens is not considered a comment, but
+	// anything following the opening or closing token, on the same line, is
+	// ignored. As such we simply treat any line prefixed with "<!--" or "-->"
+	// as if it were actually prefixed with "//" and move on.
+	case '<':
+		if i+3 < len(s) && bytes.Equal(commentStart, s[i:i+4]) {
+			c.state, i = stateJSHTMLOpenCmt, i+3
+		}
+	case '-':
+		if i+2 < len(s) && bytes.Equal(commentEnd, s[i:i+3]) {
+			c.state, i = stateJSHTMLCloseCmt, i+2
+		}
+	// ECMAScript also supports "hashbang" comment lines, see Section 12.5.
+	case '#':
+		if i+1 < len(s) && s[i+1] == '!' {
+			c.state, i = stateJSLineCmt, i+1
+		}
 	default:
 		panic("unreachable")
 	}
@@ -372,12 +394,12 @@ func tBlockCmt(c context, s []byte) (context, int) {
 	return c, i + 2
 }
 
-// tLineCmt is the context transition function for //comment states.
+// tLineCmt is the context transition function for //comment states, and the JS HTML-like comment state.
 func tLineCmt(c context, s []byte) (context, int) {
 	var lineTerminators string
 	var endState state
 	switch c.state {
-	case stateJSLineCmt:
+	case stateJSLineCmt, stateJSHTMLOpenCmt, stateJSHTMLCloseCmt:
 		lineTerminators, endState = "\n\r\u2028\u2029", stateJS
 	case stateCSSLineCmt:
 		lineTerminators, endState = "\n\f\r", stateCSS
-- 
2.24.4