From: Shubham Kulkarni <skulka...@mvista.com> html/template: disallow actions in JS template literals
Backport from https://github.com/golang/go/commit/b1e3ecfa06b67014429a197ec5e134ce4303ad9b Signed-off-by: Shubham Kulkarni <skulka...@mvista.com> --- meta/recipes-devtools/go/go-1.14.inc | 2 + .../go/go-1.14/CVE-2023-24538-1.patch | 633 +++++++++++++++++++++ .../go/go-1.14/CVE-2023-24538-2.patch | 371 ++++++++++++ 3 files changed, 1006 insertions(+) create mode 100644 meta/recipes-devtools/go/go-1.14/CVE-2023-24538-1.patch create mode 100644 meta/recipes-devtools/go/go-1.14/CVE-2023-24538-2.patch diff --git a/meta/recipes-devtools/go/go-1.14.inc b/meta/recipes-devtools/go/go-1.14.inc index 56f4f12..01f9f1e 100644 --- a/meta/recipes-devtools/go/go-1.14.inc +++ b/meta/recipes-devtools/go/go-1.14.inc @@ -57,6 +57,8 @@ SRC_URI += "\ file://CVE-2022-41722-2.patch \ file://CVE-2020-29510.patch \ file://CVE-2023-24537.patch \ + file://CVE-2023-24538-1.patch \ + file://CVE-2023-24538-2.patch \ " SRC_URI_append_libc-musl = " file://0009-ld-replace-glibc-dynamic-linker-with-musl.patch" diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-24538-1.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-24538-1.patch new file mode 100644 index 0000000..4b0d200 --- /dev/null +++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-24538-1.patch @@ -0,0 +1,633 @@ +From 64779a6dfb11631133ff3cfba7ae7e449c191a88 Mon Sep 17 00:00:00 2001 +From: empijei <robcl...@gmail.com> +Date: Fri, 27 Mar 2020 19:27:55 +0100 +Subject: [PATCH 1/2] html/template,text/template: switch to Unicode escapes + for JSON compatibility +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The existing implementation is not compatible with JSON +escape as it uses hex escaping. +Unicode escape, instead, is valid for both JSON and JS. +This fix avoids creating a separate escaping context for +scripts of type "application/ld+json" and it is more +future-proof in case more JSON+JS contexts get added +to the platform (e.g. import maps). + +Fixes #33671 +Fixes #37634 + +Change-Id: Id6f6524b4abc52e81d9d744d46bbe5bf2e081543 +Reviewed-on: https://go-review.googlesource.com/c/go/+/226097 +Reviewed-by: Carl Johnson <m...@carlmjohnson.net> +Reviewed-by: Daniel Martí <mv...@mvdan.cc> +Run-TryBot: Daniel Martí <mv...@mvdan.cc> +TryBot-Result: Gobot Gobot <go...@golang.org> + +Upstream-Status: Backport from https://github.com/golang/go/commit/d4d298040d072ddacea0e0d6b55fb148fff18070 +CVE: CVE-2023-24538 +Signed-off-by: Shubham Kulkarni <skulka...@mvista.com> +--- + src/html/template/content_test.go | 70 +++++++++++++++++++------------------- + src/html/template/escape_test.go | 6 ++-- + src/html/template/example_test.go | 6 ++-- + src/html/template/js.go | 70 +++++++++++++++++++++++--------------- + src/html/template/js_test.go | 68 ++++++++++++++++++------------------ + src/html/template/template_test.go | 39 +++++++++++++++++++++ + src/text/template/exec_test.go | 6 ++-- + src/text/template/funcs.go | 8 ++--- + 8 files changed, 163 insertions(+), 110 deletions(-) + +diff --git a/src/html/template/content_test.go b/src/html/template/content_test.go +index 72d56f5..bd86527 100644 +--- a/src/html/template/content_test.go ++++ b/src/html/template/content_test.go +@@ -18,7 +18,7 @@ func TestTypedContent(t *testing.T) { + HTML(`Hello, <b>World</b> &tc!`), + HTMLAttr(` dir="ltr"`), + JS(`c && alert("Hello, World!");`), +- JSStr(`Hello, World & O'Reilly\x21`), ++ JSStr(`Hello, World & O'Reilly\u0021`), + URL(`greeting=H%69,&addressee=(World)`), + Srcset(`greeting=H%69,&addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`), + URL(`,foo/,`), +@@ -70,7 +70,7 @@ func TestTypedContent(t *testing.T) { + `Hello, <b>World</b> &tc!`, + ` dir="ltr"`, + `c && alert("Hello, World!");`, +- `Hello, World & O'Reilly\x21`, ++ `Hello, World & O'Reilly\u0021`, + `greeting=H%69,&addressee=(World)`, + `greeting=H%69,&addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`, + `,foo/,`, +@@ -100,7 +100,7 @@ func TestTypedContent(t *testing.T) { + `Hello, World &tc!`, + ` dir="ltr"`, + `c && alert("Hello, World!");`, +- `Hello, World & O'Reilly\x21`, ++ `Hello, World & O'Reilly\u0021`, + `greeting=H%69,&addressee=(World)`, + `greeting=H%69,&addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`, + `,foo/,`, +@@ -115,7 +115,7 @@ func TestTypedContent(t *testing.T) { + `Hello, World &tc!`, + ` dir="ltr"`, + `c && alert("Hello, World!");`, +- `Hello, World & O'Reilly\x21`, ++ `Hello, World & O'Reilly\u0021`, + `greeting=H%69,&addressee=(World)`, + `greeting=H%69,&addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`, + `,foo/,`, +@@ -130,7 +130,7 @@ func TestTypedContent(t *testing.T) { + `Hello, <b>World</b> &tc!`, + ` dir="ltr"`, + `c && alert("Hello, World!");`, +- `Hello, World & O'Reilly\x21`, ++ `Hello, World & O'Reilly\u0021`, + `greeting=H%69,&addressee=(World)`, + `greeting=H%69,&addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`, + `,foo/,`, +@@ -146,7 +146,7 @@ func TestTypedContent(t *testing.T) { + // Not escaped. + `c && alert("Hello, World!");`, + // Escape sequence not over-escaped. +- `"Hello, World & O'Reilly\x21"`, ++ `"Hello, World & O'Reilly\u0021"`, + `"greeting=H%69,\u0026addressee=(World)"`, + `"greeting=H%69,\u0026addressee=(World) 2x, https://golang.org/favicon.ico 500.5w"`, + `",foo/,"`, +@@ -162,7 +162,7 @@ func TestTypedContent(t *testing.T) { + // Not JS escaped but HTML escaped. + `c && alert("Hello, World!");`, + // Escape sequence not over-escaped. +- `"Hello, World & O'Reilly\x21"`, ++ `"Hello, World & O'Reilly\u0021"`, + `"greeting=H%69,\u0026addressee=(World)"`, + `"greeting=H%69,\u0026addressee=(World) 2x, https://golang.org/favicon.ico 500.5w"`, + `",foo/,"`, +@@ -171,30 +171,30 @@ func TestTypedContent(t *testing.T) { + { + `<script>alert("{{.}}")</script>`, + []string{ +- `\x3cb\x3e \x22foo%\x22 O\x27Reilly \x26bar;`, +- `a[href =~ \x22\/\/example.com\x22]#foo`, +- `Hello, \x3cb\x3eWorld\x3c\/b\x3e \x26amp;tc!`, +- ` dir=\x22ltr\x22`, +- `c \x26\x26 alert(\x22Hello, World!\x22);`, ++ `\u003cb\u003e \u0022foo%\u0022 O\u0027Reilly \u0026bar;`, ++ `a[href =~ \u0022\/\/example.com\u0022]#foo`, ++ `Hello, \u003cb\u003eWorld\u003c\/b\u003e \u0026amp;tc!`, ++ ` dir=\u0022ltr\u0022`, ++ `c \u0026\u0026 alert(\u0022Hello, World!\u0022);`, + // Escape sequence not over-escaped. +- `Hello, World \x26 O\x27Reilly\x21`, +- `greeting=H%69,\x26addressee=(World)`, +- `greeting=H%69,\x26addressee=(World) 2x, https:\/\/golang.org\/favicon.ico 500.5w`, ++ `Hello, World \u0026 O\u0027Reilly\u0021`, ++ `greeting=H%69,\u0026addressee=(World)`, ++ `greeting=H%69,\u0026addressee=(World) 2x, https:\/\/golang.org\/favicon.ico 500.5w`, + `,foo\/,`, + }, + }, + { + `<script type="text/javascript">alert("{{.}}")</script>`, + []string{ +- `\x3cb\x3e \x22foo%\x22 O\x27Reilly \x26bar;`, +- `a[href =~ \x22\/\/example.com\x22]#foo`, +- `Hello, \x3cb\x3eWorld\x3c\/b\x3e \x26amp;tc!`, +- ` dir=\x22ltr\x22`, +- `c \x26\x26 alert(\x22Hello, World!\x22);`, ++ `\u003cb\u003e \u0022foo%\u0022 O\u0027Reilly \u0026bar;`, ++ `a[href =~ \u0022\/\/example.com\u0022]#foo`, ++ `Hello, \u003cb\u003eWorld\u003c\/b\u003e \u0026amp;tc!`, ++ ` dir=\u0022ltr\u0022`, ++ `c \u0026\u0026 alert(\u0022Hello, World!\u0022);`, + // Escape sequence not over-escaped. +- `Hello, World \x26 O\x27Reilly\x21`, +- `greeting=H%69,\x26addressee=(World)`, +- `greeting=H%69,\x26addressee=(World) 2x, https:\/\/golang.org\/favicon.ico 500.5w`, ++ `Hello, World \u0026 O\u0027Reilly\u0021`, ++ `greeting=H%69,\u0026addressee=(World)`, ++ `greeting=H%69,\u0026addressee=(World) 2x, https:\/\/golang.org\/favicon.ico 500.5w`, + `,foo\/,`, + }, + }, +@@ -208,7 +208,7 @@ func TestTypedContent(t *testing.T) { + // Not escaped. + `c && alert("Hello, World!");`, + // Escape sequence not over-escaped. +- `"Hello, World & O'Reilly\x21"`, ++ `"Hello, World & O'Reilly\u0021"`, + `"greeting=H%69,\u0026addressee=(World)"`, + `"greeting=H%69,\u0026addressee=(World) 2x, https://golang.org/favicon.ico 500.5w"`, + `",foo/,"`, +@@ -224,7 +224,7 @@ func TestTypedContent(t *testing.T) { + `Hello, <b>World</b> &tc!`, + ` dir="ltr"`, + `c && alert("Hello, World!");`, +- `Hello, World & O'Reilly\x21`, ++ `Hello, World & O'Reilly\u0021`, + `greeting=H%69,&addressee=(World)`, + `greeting=H%69,&addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`, + `,foo/,`, +@@ -233,15 +233,15 @@ func TestTypedContent(t *testing.T) { + { + `<button onclick='alert("{{.}}")'>`, + []string{ +- `\x3cb\x3e \x22foo%\x22 O\x27Reilly \x26bar;`, +- `a[href =~ \x22\/\/example.com\x22]#foo`, +- `Hello, \x3cb\x3eWorld\x3c\/b\x3e \x26amp;tc!`, +- ` dir=\x22ltr\x22`, +- `c \x26\x26 alert(\x22Hello, World!\x22);`, ++ `\u003cb\u003e \u0022foo%\u0022 O\u0027Reilly \u0026bar;`, ++ `a[href =~ \u0022\/\/example.com\u0022]#foo`, ++ `Hello, \u003cb\u003eWorld\u003c\/b\u003e \u0026amp;tc!`, ++ ` dir=\u0022ltr\u0022`, ++ `c \u0026\u0026 alert(\u0022Hello, World!\u0022);`, + // Escape sequence not over-escaped. +- `Hello, World \x26 O\x27Reilly\x21`, +- `greeting=H%69,\x26addressee=(World)`, +- `greeting=H%69,\x26addressee=(World) 2x, https:\/\/golang.org\/favicon.ico 500.5w`, ++ `Hello, World \u0026 O\u0027Reilly\u0021`, ++ `greeting=H%69,\u0026addressee=(World)`, ++ `greeting=H%69,\u0026addressee=(World) 2x, https:\/\/golang.org\/favicon.ico 500.5w`, + `,foo\/,`, + }, + }, +@@ -253,7 +253,7 @@ func TestTypedContent(t *testing.T) { + `Hello%2c%20%3cb%3eWorld%3c%2fb%3e%20%26amp%3btc%21`, + `%20dir%3d%22ltr%22`, + `c%20%26%26%20alert%28%22Hello%2c%20World%21%22%29%3b`, +- `Hello%2c%20World%20%26%20O%27Reilly%5cx21`, ++ `Hello%2c%20World%20%26%20O%27Reilly%5cu0021`, + // Quotes and parens are escaped but %69 is not over-escaped. HTML escaping is done. + `greeting=H%69,&addressee=%28World%29`, + `greeting%3dH%2569%2c%26addressee%3d%28World%29%202x%2c%20https%3a%2f%2fgolang.org%2ffavicon.ico%20500.5w`, +@@ -268,7 +268,7 @@ func TestTypedContent(t *testing.T) { + `Hello%2c%20%3cb%3eWorld%3c%2fb%3e%20%26amp%3btc%21`, + `%20dir%3d%22ltr%22`, + `c%20%26%26%20alert%28%22Hello%2c%20World%21%22%29%3b`, +- `Hello%2c%20World%20%26%20O%27Reilly%5cx21`, ++ `Hello%2c%20World%20%26%20O%27Reilly%5cu0021`, + // Quotes and parens are escaped but %69 is not over-escaped. HTML escaping is not done. + `greeting=H%69,&addressee=%28World%29`, + `greeting%3dH%2569%2c%26addressee%3d%28World%29%202x%2c%20https%3a%2f%2fgolang.org%2ffavicon.ico%20500.5w`, +diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go +index e72a9ba..c709660 100644 +--- a/src/html/template/escape_test.go ++++ b/src/html/template/escape_test.go +@@ -238,7 +238,7 @@ func TestEscape(t *testing.T) { + { + "jsStr", + "<button onclick='alert("{{.H}}")'>", +- `<button onclick='alert("\x3cHello\x3e")'>`, ++ `<button onclick='alert("\u003cHello\u003e")'>`, + }, + { + "badMarshaler", +@@ -259,7 +259,7 @@ func TestEscape(t *testing.T) { + { + "jsRe", + `<button onclick='alert(/{{"foo+bar"}}/.test(""))'>`, +- `<button onclick='alert(/foo\x2bbar/.test(""))'>`, ++ `<button onclick='alert(/foo\u002bbar/.test(""))'>`, + }, + { + "jsReBlank", +@@ -825,7 +825,7 @@ func TestEscapeSet(t *testing.T) { + "main": `<button onclick="title='{{template "helper"}}'; ...">{{template "helper"}}</button>`, + "helper": `{{11}} of {{"<100>"}}`, + }, +- `<button onclick="title='11 of \x3c100\x3e'; ...">11 of <100></button>`, ++ `<button onclick="title='11 of \u003c100\u003e'; ...">11 of <100></button>`, + }, + // A non-recursive template that ends in a different context. + // helper starts in jsCtxRegexp and ends in jsCtxDivOp. +diff --git a/src/html/template/example_test.go b/src/html/template/example_test.go +index 9d965f1..6cf936f 100644 +--- a/src/html/template/example_test.go ++++ b/src/html/template/example_test.go +@@ -116,9 +116,9 @@ func Example_escape() { + // "Fran & Freddie's Diner" <ta...@example.com> + // "Fran & Freddie's Diner" <ta...@example.com> + // "Fran & Freddie's Diner"32<ta...@example.com> +- // \"Fran \x26 Freddie\'s Diner\" \x3cta...@example.com\x3E +- // \"Fran \x26 Freddie\'s Diner\" \x3cta...@example.com\x3E +- // \"Fran \x26 Freddie\'s Diner\"32\x3cta...@example.com\x3E ++ // \"Fran \u0026 Freddie\'s Diner\" \u003cta...@example.com\u003E ++ // \"Fran \u0026 Freddie\'s Diner\" \u003cta...@example.com\u003E ++ // \"Fran \u0026 Freddie\'s Diner\"32\u003cta...@example.com\u003E + // %22Fran+%26+Freddie%27s+Diner%2232%3Ctasty%40example.com%3E + + } +diff --git a/src/html/template/js.go b/src/html/template/js.go +index 0e91458..ea9c183 100644 +--- a/src/html/template/js.go ++++ b/src/html/template/js.go +@@ -163,7 +163,6 @@ func jsValEscaper(args ...interface{}) string { + } + // TODO: detect cycles before calling Marshal which loops infinitely on + // cyclic data. This may be an unacceptable DoS risk. +- + b, err := json.Marshal(a) + if err != nil { + // Put a space before comment so that if it is flush against +@@ -178,8 +177,8 @@ func jsValEscaper(args ...interface{}) string { + // TODO: maybe post-process output to prevent it from containing + // "<!--", "-->", "<![CDATA[", "]]>", or "</script" + // in case custom marshalers produce output containing those. +- +- // TODO: Maybe abbreviate \u00ab to \xab to produce more compact output. ++ // Note: Do not use \x escaping to save bytes because it is not JSON compatible and this escaper ++ // supports ld+json content-type. + if len(b) == 0 { + // In, `x=y/{{.}}*z` a json.Marshaler that produces "" should + // not cause the output `x=y/*z`. +@@ -260,6 +259,8 @@ func replace(s string, replacementTable []string) string { + r, w = utf8.DecodeRuneInString(s[i:]) + var repl string + switch { ++ case int(r) < len(lowUnicodeReplacementTable): ++ repl = lowUnicodeReplacementTable[r] + case int(r) < len(replacementTable) && replacementTable[r] != "": + repl = replacementTable[r] + case r == '\u2028': +@@ -283,67 +284,80 @@ func replace(s string, replacementTable []string) string { + return b.String() + } + ++var lowUnicodeReplacementTable = []string{ ++ 0: `\u0000`, 1: `\u0001`, 2: `\u0002`, 3: `\u0003`, 4: `\u0004`, 5: `\u0005`, 6: `\u0006`, ++ '\a': `\u0007`, ++ '\b': `\u0008`, ++ '\t': `\t`, ++ '\n': `\n`, ++ '\v': `\u000b`, // "\v" == "v" on IE 6. ++ '\f': `\f`, ++ '\r': `\r`, ++ 0xe: `\u000e`, 0xf: `\u000f`, 0x10: `\u0010`, 0x11: `\u0011`, 0x12: `\u0012`, 0x13: `\u0013`, ++ 0x14: `\u0014`, 0x15: `\u0015`, 0x16: `\u0016`, 0x17: `\u0017`, 0x18: `\u0018`, 0x19: `\u0019`, ++ 0x1a: `\u001a`, 0x1b: `\u001b`, 0x1c: `\u001c`, 0x1d: `\u001d`, 0x1e: `\u001e`, 0x1f: `\u001f`, ++} ++ + var jsStrReplacementTable = []string{ +- 0: `\0`, ++ 0: `\u0000`, + '\t': `\t`, + '\n': `\n`, +- '\v': `\x0b`, // "\v" == "v" on IE 6. ++ '\v': `\u000b`, // "\v" == "v" on IE 6. + '\f': `\f`, + '\r': `\r`, + // Encode HTML specials as hex so the output can be embedded + // in HTML attributes without further encoding. +- '"': `\x22`, +- '&': `\x26`, +- '\'': `\x27`, +- '+': `\x2b`, ++ '"': `\u0022`, ++ '&': `\u0026`, ++ '\'': `\u0027`, ++ '+': `\u002b`, + '/': `\/`, +- '<': `\x3c`, +- '>': `\x3e`, ++ '<': `\u003c`, ++ '>': `\u003e`, + '\\': `\\`, + } + + // jsStrNormReplacementTable is like jsStrReplacementTable but does not + // overencode existing escapes since this table has no entry for `\`. + var jsStrNormReplacementTable = []string{ +- 0: `\0`, ++ 0: `\u0000`, + '\t': `\t`, + '\n': `\n`, +- '\v': `\x0b`, // "\v" == "v" on IE 6. ++ '\v': `\u000b`, // "\v" == "v" on IE 6. + '\f': `\f`, + '\r': `\r`, + // Encode HTML specials as hex so the output can be embedded + // in HTML attributes without further encoding. +- '"': `\x22`, +- '&': `\x26`, +- '\'': `\x27`, +- '+': `\x2b`, ++ '"': `\u0022`, ++ '&': `\u0026`, ++ '\'': `\u0027`, ++ '+': `\u002b`, + '/': `\/`, +- '<': `\x3c`, +- '>': `\x3e`, ++ '<': `\u003c`, ++ '>': `\u003e`, + } +- + var jsRegexpReplacementTable = []string{ +- 0: `\0`, ++ 0: `\u0000`, + '\t': `\t`, + '\n': `\n`, +- '\v': `\x0b`, // "\v" == "v" on IE 6. ++ '\v': `\u000b`, // "\v" == "v" on IE 6. + '\f': `\f`, + '\r': `\r`, + // Encode HTML specials as hex so the output can be embedded + // in HTML attributes without further encoding. +- '"': `\x22`, ++ '"': `\u0022`, + '$': `\$`, +- '&': `\x26`, +- '\'': `\x27`, ++ '&': `\u0026`, ++ '\'': `\u0027`, + '(': `\(`, + ')': `\)`, + '*': `\*`, +- '+': `\x2b`, ++ '+': `\u002b`, + '-': `\-`, + '.': `\.`, + '/': `\/`, +- '<': `\x3c`, +- '>': `\x3e`, ++ '<': `\u003c`, ++ '>': `\u003e`, + '?': `\?`, + '[': `\[`, + '\\': `\\`, +diff --git a/src/html/template/js_test.go b/src/html/template/js_test.go +index 075adaa..d7ee47b 100644 +--- a/src/html/template/js_test.go ++++ b/src/html/template/js_test.go +@@ -137,7 +137,7 @@ func TestJSValEscaper(t *testing.T) { + {"foo", `"foo"`}, + // Newlines. + {"\r\n\u2028\u2029", `"\r\n\u2028\u2029"`}, +- // "\v" == "v" on IE 6 so use "\x0b" instead. ++ // "\v" == "v" on IE 6 so use "\u000b" instead. + {"\t\x0b", `"\t\u000b"`}, + {struct{ X, Y int }{1, 2}, `{"X":1,"Y":2}`}, + {[]interface{}{}, "[]"}, +@@ -173,7 +173,7 @@ func TestJSStrEscaper(t *testing.T) { + }{ + {"", ``}, + {"foo", `foo`}, +- {"\u0000", `\0`}, ++ {"\u0000", `\u0000`}, + {"\t", `\t`}, + {"\n", `\n`}, + {"\r", `\r`}, +@@ -183,14 +183,14 @@ func TestJSStrEscaper(t *testing.T) { + {"\\n", `\\n`}, + {"foo\r\nbar", `foo\r\nbar`}, + // Preserve attribute boundaries. +- {`"`, `\x22`}, +- {`'`, `\x27`}, ++ {`"`, `\u0022`}, ++ {`'`, `\u0027`}, + // Allow embedding in HTML without further escaping. +- {`&`, `\x26amp;`}, ++ {`&`, `\u0026amp;`}, + // Prevent breaking out of text node and element boundaries. +- {"</script>", `\x3c\/script\x3e`}, +- {"<![CDATA[", `\x3c![CDATA[`}, +- {"]]>", `]]\x3e`}, ++ {"</script>", `\u003c\/script\u003e`}, ++ {"<![CDATA[", `\u003c![CDATA[`}, ++ {"]]>", `]]\u003e`}, + // https://dev.w3.org/html5/markup/aria/syntax.html#escaping-text-span + // "The text in style, script, title, and textarea elements + // must not have an escaping text span start that is not +@@ -201,11 +201,11 @@ func TestJSStrEscaper(t *testing.T) { + // allow regular text content to be interpreted as script + // allowing script execution via a combination of a JS string + // injection followed by an HTML text injection. +- {"<!--", `\x3c!--`}, +- {"-->", `--\x3e`}, ++ {"<!--", `\u003c!--`}, ++ {"-->", `--\u003e`}, + // From https://code.google.com/p/doctype/wiki/ArticleUtf7 + {"+ADw-script+AD4-alert(1)+ADw-/script+AD4-", +- `\x2bADw-script\x2bAD4-alert(1)\x2bADw-\/script\x2bAD4-`, ++ `\u002bADw-script\u002bAD4-alert(1)\u002bADw-\/script\u002bAD4-`, + }, + // Invalid UTF-8 sequence + {"foo\xA0bar", "foo\xA0bar"}, +@@ -228,7 +228,7 @@ func TestJSRegexpEscaper(t *testing.T) { + }{ + {"", `(?:)`}, + {"foo", `foo`}, +- {"\u0000", `\0`}, ++ {"\u0000", `\u0000`}, + {"\t", `\t`}, + {"\n", `\n`}, + {"\r", `\r`}, +@@ -238,19 +238,19 @@ func TestJSRegexpEscaper(t *testing.T) { + {"\\n", `\\n`}, + {"foo\r\nbar", `foo\r\nbar`}, + // Preserve attribute boundaries. +- {`"`, `\x22`}, +- {`'`, `\x27`}, ++ {`"`, `\u0022`}, ++ {`'`, `\u0027`}, + // Allow embedding in HTML without further escaping. +- {`&`, `\x26amp;`}, ++ {`&`, `\u0026amp;`}, + // Prevent breaking out of text node and element boundaries. +- {"</script>", `\x3c\/script\x3e`}, +- {"<![CDATA[", `\x3c!\[CDATA\[`}, +- {"]]>", `\]\]\x3e`}, ++ {"</script>", `\u003c\/script\u003e`}, ++ {"<![CDATA[", `\u003c!\[CDATA\[`}, ++ {"]]>", `\]\]\u003e`}, + // Escaping text spans. +- {"<!--", `\x3c!\-\-`}, +- {"-->", `\-\-\x3e`}, ++ {"<!--", `\u003c!\-\-`}, ++ {"-->", `\-\-\u003e`}, + {"*", `\*`}, +- {"+", `\x2b`}, ++ {"+", `\u002b`}, + {"?", `\?`}, + {"[](){}", `\[\]\(\)\{\}`}, + {"$foo|x.y", `\$foo\|x\.y`}, +@@ -284,27 +284,27 @@ func TestEscapersOnLower7AndSelectHighCodepoints(t *testing.T) { + { + "jsStrEscaper", + jsStrEscaper, +- "\\0\x01\x02\x03\x04\x05\x06\x07" + +- "\x08\\t\\n\\x0b\\f\\r\x0E\x0F" + +- "\x10\x11\x12\x13\x14\x15\x16\x17" + +- "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + +- ` !\x22#$%\x26\x27()*\x2b,-.\/` + +- `0123456789:;\x3c=\x3e?` + ++ `\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007` + ++ `\u0008\t\n\u000b\f\r\u000e\u000f` + ++ `\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017` + ++ `\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f` + ++ ` !\u0022#$%\u0026\u0027()*\u002b,-.\/` + ++ `0123456789:;\u003c=\u003e?` + + `@ABCDEFGHIJKLMNO` + + `PQRSTUVWXYZ[\\]^_` + + "`abcdefghijklmno" + +- "pqrstuvwxyz{|}~\x7f" + ++ "pqrstuvwxyz{|}~\u007f" + + "\u00A0\u0100\\u2028\\u2029\ufeff\U0001D11E", + }, + { + "jsRegexpEscaper", + jsRegexpEscaper, +- "\\0\x01\x02\x03\x04\x05\x06\x07" + +- "\x08\\t\\n\\x0b\\f\\r\x0E\x0F" + +- "\x10\x11\x12\x13\x14\x15\x16\x17" + +- "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + +- ` !\x22#\$%\x26\x27\(\)\*\x2b,\-\.\/` + +- `0123456789:;\x3c=\x3e\?` + ++ `\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007` + ++ `\u0008\t\n\u000b\f\r\u000e\u000f` + ++ `\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017` + ++ `\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f` + ++ ` !\u0022#\$%\u0026\u0027\(\)\*\u002b,\-\.\/` + ++ `0123456789:;\u003c=\u003e\?` + + `@ABCDEFGHIJKLMNO` + + `PQRSTUVWXYZ\[\\\]\^_` + + "`abcdefghijklmno" + +diff --git a/src/html/template/template_test.go b/src/html/template/template_test.go +index 13e6ba4..86bd4db 100644 +--- a/src/html/template/template_test.go ++++ b/src/html/template/template_test.go +@@ -6,6 +6,7 @@ package template_test + + import ( + "bytes" ++ "encoding/json" + . "html/template" + "strings" + "testing" +@@ -121,6 +122,44 @@ func TestNumbers(t *testing.T) { + c.mustExecute(c.root, nil, "12.34 7.5") + } + ++func TestStringsInScriptsWithJsonContentTypeAreCorrectlyEscaped(t *testing.T) { ++ // See #33671 and #37634 for more context on this. ++ tests := []struct{ name, in string }{ ++ {"empty", ""}, ++ {"invalid", string(rune(-1))}, ++ {"null", "\u0000"}, ++ {"unit separator", "\u001F"}, ++ {"tab", "\t"}, ++ {"gt and lt", "<>"}, ++ {"quotes", `'"`}, ++ {"ASCII letters", "ASCII letters"}, ++ {"Unicode", "ʕ⊙ϖ⊙ʔ"}, ++ {"Pizza", "🍕"}, ++ } ++ const ( ++ prefix = `<script type="application/ld+json">` ++ suffix = `</script>` ++ templ = prefix + `"{{.}}"` + suffix ++ ) ++ tpl := Must(New("JS string is JSON string").Parse(templ)) ++ for _, tt := range tests { ++ t.Run(tt.name, func(t *testing.T) { ++ var buf bytes.Buffer ++ if err := tpl.Execute(&buf, tt.in); err != nil { ++ t.Fatalf("Cannot render template: %v", err) ++ } ++ trimmed := bytes.TrimSuffix(bytes.TrimPrefix(buf.Bytes(), []byte(prefix)), []byte(suffix)) ++ var got string ++ if err := json.Unmarshal(trimmed, &got); err != nil { ++ t.Fatalf("Cannot parse JS string %q as JSON: %v", trimmed[1:len(trimmed)-1], err) ++ } ++ if got != tt.in { ++ t.Errorf("Serialization changed the string value: got %q want %q", got, tt.in) ++ } ++ }) ++ } ++} ++ + type testCase struct { + t *testing.T + root *Template +diff --git a/src/text/template/exec_test.go b/src/text/template/exec_test.go +index 77294ed..b8a809e 100644 +--- a/src/text/template/exec_test.go ++++ b/src/text/template/exec_test.go +@@ -911,9 +911,9 @@ func TestJSEscaping(t *testing.T) { + {`Go "jump" \`, `Go \"jump\" \\`}, + {`Yukihiro says "今日は世界"`, `Yukihiro says \"今日は世界\"`}, + {"unprintable \uFDFF", `unprintable \uFDFF`}, +- {`<html>`, `\x3Chtml\x3E`}, +- {`no = in attributes`, `no \x3D in attributes`}, +- {`' does not become HTML entity`, `\x26#x27; does not become HTML entity`}, ++ {`<html>`, `\u003Chtml\u003E`}, ++ {`no = in attributes`, `no \u003D in attributes`}, ++ {`' does not become HTML entity`, `\u0026#x27; does not become HTML entity`}, + } + for _, tc := range testCases { + s := JSEscapeString(tc.in) +diff --git a/src/text/template/funcs.go b/src/text/template/funcs.go +index 46125bc..f3de9fb 100644 +--- a/src/text/template/funcs.go ++++ b/src/text/template/funcs.go +@@ -640,10 +640,10 @@ var ( + jsBackslash = []byte(`\\`) + jsApos = []byte(`\'`) + jsQuot = []byte(`\"`) +- jsLt = []byte(`\x3C`) +- jsGt = []byte(`\x3E`) +- jsAmp = []byte(`\x26`) +- jsEq = []byte(`\x3D`) ++ jsLt = []byte(`\u003C`) ++ jsGt = []byte(`\u003E`) ++ jsAmp = []byte(`\u0026`) ++ jsEq = []byte(`\u003D`) + ) + + // JSEscape writes to w the escaped JavaScript equivalent of the plain text data b. +-- +2.7.4 diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-24538-2.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-24538-2.patch new file mode 100644 index 0000000..5f5a2d9 --- /dev/null +++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-24538-2.patch @@ -0,0 +1,371 @@ +From 576db9a3262931fcda4dbf1b78b56d4565a5ad3f Mon Sep 17 00:00:00 2001 +From: Roland Shoemaker <bracew...@google.com> +Date: Mon, 20 Mar 2023 11:01:13 -0700 +Subject: [PATCH 2/2] html/template: disallow actions in JS template literals + +ECMAScript 6 introduced template literals[0][1] which are delimited with +backticks. These need to be escaped in a similar fashion to the +delimiters for other string literals. Additionally template literals can +contain special syntax for string interpolation. + +There is no clear way to allow safe insertion of actions within JS +template literals, as handling (JS) string interpolation inside of these +literals is rather complex. As such we've chosen to simply disallow +template actions within these template literals. + +A new error code is added for this parsing failure case, errJsTmplLit, +but it is unexported as it is not backwards compatible with other minor +release versions to introduce an API change in a minor release. We will +export this code in the next major release. + +The previous behavior (with the cavet that backticks are now escaped +properly) can be re-enabled with GODEBUG=jstmpllitinterp=1. + +This change subsumes CL471455. + +Thanks to Sohom Datta, Manipal Institute of Technology, for reporting +this issue. + +Fixes CVE-2023-24538 +For #59234 +Fixes #59271 + +[0] https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-template-literals +[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals + +Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1802457 +Reviewed-by: Damien Neil <dn...@google.com> +Run-TryBot: Damien Neil <dn...@google.com> +Reviewed-by: Julie Qiu <julie...@google.com> +Reviewed-by: Roland Shoemaker <bracew...@google.com> +Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1802612 +Run-TryBot: Roland Shoemaker <bracew...@google.com> +Change-Id: Ic7f10595615f2b2740d9c85ad7ef40dc0e78c04c +Reviewed-on: https://go-review.googlesource.com/c/go/+/481987 +Auto-Submit: Michael Knyszek <mknys...@google.com> +TryBot-Result: Gopher Robot <go...@golang.org> +Run-TryBot: Michael Knyszek <mknys...@google.com> +Reviewed-by: Matthew Dempsky <mdemp...@google.com> + +Upstream-Status: Backport from https://github.com/golang/go/commit/b1e3ecfa06b67014429a197ec5e134ce4303ad9b +CVE: CVE-2023-24538 +Signed-off-by: Shubham Kulkarni <skulka...@mvista.com> +--- + src/html/template/context.go | 2 ++ + src/html/template/error.go | 13 ++++++++ + src/html/template/escape.go | 11 +++++++ + src/html/template/escape_test.go | 66 ++++++++++++++++++++++----------------- + src/html/template/js.go | 2 ++ + src/html/template/js_test.go | 2 +- + src/html/template/jsctx_string.go | 9 ++++++ + src/html/template/state_string.go | 37 ++++++++++++++++++++-- + src/html/template/transition.go | 7 ++++- + 9 files changed, 116 insertions(+), 33 deletions(-) + +diff --git a/src/html/template/context.go b/src/html/template/context.go +index f7d4849..0b65313 100644 +--- a/src/html/template/context.go ++++ b/src/html/template/context.go +@@ -116,6 +116,8 @@ const ( + stateJSDqStr + // stateJSSqStr occurs inside a JavaScript single quoted string. + stateJSSqStr ++ // stateJSBqStr occurs inside a JavaScript back quoted string. ++ stateJSBqStr + // stateJSRegexp occurs inside a JavaScript regexp literal. + stateJSRegexp + // stateJSBlockCmt occurs inside a JavaScript /* block comment */. +diff --git a/src/html/template/error.go b/src/html/template/error.go +index 0e52706..fd26b64 100644 +--- a/src/html/template/error.go ++++ b/src/html/template/error.go +@@ -211,6 +211,19 @@ const ( + // pipeline occurs in an unquoted attribute value context, "html" is + // disallowed. Avoid using "html" and "urlquery" entirely in new templates. + ErrPredefinedEscaper ++ ++ // errJSTmplLit: "... appears in a JS template literal" ++ // Example: ++ // <script>var tmpl = `{{.Interp}`</script> ++ // Discussion: ++ // Package html/template does not support actions inside of JS template ++ // literals. ++ // ++ // TODO(rolandshoemaker): we cannot add this as an exported error in a minor ++ // release, since it is backwards incompatible with the other minor ++ // releases. As such we need to leave it unexported, and then we'll add it ++ // in the next major release. ++ errJSTmplLit + ) + + func (e *Error) Error() string { +diff --git a/src/html/template/escape.go b/src/html/template/escape.go +index f12dafa..29ca5b3 100644 +--- a/src/html/template/escape.go ++++ b/src/html/template/escape.go +@@ -8,6 +8,7 @@ import ( + "bytes" + "fmt" + "html" ++ "internal/godebug" + "io" + "text/template" + "text/template/parse" +@@ -203,6 +204,16 @@ func (e *escaper) escapeAction(c context, n *parse.ActionNode) context { + c.jsCtx = jsCtxDivOp + case stateJSDqStr, stateJSSqStr: + s = append(s, "_html_template_jsstrescaper") ++ case stateJSBqStr: ++ debugAllowActionJSTmpl := godebug.Get("jstmpllitinterp") ++ if debugAllowActionJSTmpl == "1" { ++ s = append(s, "_html_template_jsstrescaper") ++ } else { ++ return context{ ++ state: stateError, ++ err: errorf(errJSTmplLit, n, n.Line, "%s appears in a JS template literal", n), ++ } ++ } + case stateJSRegexp: + s = append(s, "_html_template_jsregexpescaper") + case stateCSS: +diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go +index c709660..807aabd 100644 +--- a/src/html/template/escape_test.go ++++ b/src/html/template/escape_test.go +@@ -681,35 +681,31 @@ func TestEscape(t *testing.T) { + } + + for _, test := range tests { +- tmpl := New(test.name) +- tmpl = Must(tmpl.Parse(test.input)) +- // Check for bug 6459: Tree field was not set in Parse. +- if tmpl.Tree != tmpl.text.Tree { +- t.Errorf("%s: tree not set properly", test.name) +- continue +- } +- b := new(bytes.Buffer) +- if err := tmpl.Execute(b, data); err != nil { +- t.Errorf("%s: template execution failed: %s", test.name, err) +- continue +- } +- if w, g := test.output, b.String(); w != g { +- t.Errorf("%s: escaped output: want\n\t%q\ngot\n\t%q", test.name, w, g) +- continue +- } +- b.Reset() +- if err := tmpl.Execute(b, pdata); err != nil { +- t.Errorf("%s: template execution failed for pointer: %s", test.name, err) +- continue +- } +- if w, g := test.output, b.String(); w != g { +- t.Errorf("%s: escaped output for pointer: want\n\t%q\ngot\n\t%q", test.name, w, g) +- continue +- } +- if tmpl.Tree != tmpl.text.Tree { +- t.Errorf("%s: tree mismatch", test.name) +- continue +- } ++ t.Run(test.name, func(t *testing.T) { ++ tmpl := New(test.name) ++ tmpl = Must(tmpl.Parse(test.input)) ++ // Check for bug 6459: Tree field was not set in Parse. ++ if tmpl.Tree != tmpl.text.Tree { ++ t.Fatalf("%s: tree not set properly", test.name) ++ } ++ b := new(strings.Builder) ++ if err := tmpl.Execute(b, data); err != nil { ++ t.Fatalf("%s: template execution failed: %s", test.name, err) ++ } ++ if w, g := test.output, b.String(); w != g { ++ t.Fatalf("%s: escaped output: want\n\t%q\ngot\n\t%q", test.name, w, g) ++ } ++ b.Reset() ++ if err := tmpl.Execute(b, pdata); err != nil { ++ t.Fatalf("%s: template execution failed for pointer: %s", test.name, err) ++ } ++ if w, g := test.output, b.String(); w != g { ++ t.Fatalf("%s: escaped output for pointer: want\n\t%q\ngot\n\t%q", test.name, w, g) ++ } ++ if tmpl.Tree != tmpl.text.Tree { ++ t.Fatalf("%s: tree mismatch", test.name) ++ } ++ }) + } + } + +@@ -920,6 +916,10 @@ func TestErrors(t *testing.T) { + "<a href='/foo?{{range .Items}}&{{.K}}={{.V}}{{end}}'>", + "", + }, ++ { ++ "<script>var a = `${a+b}`</script>`", ++ "", ++ }, + // Error cases. + { + "{{if .Cond}}<a{{end}}", +@@ -1058,6 +1058,10 @@ func TestErrors(t *testing.T) { + // html is allowed since it is the last command in the pipeline, but urlquery is not. + `predefined escaper "urlquery" disallowed in template`, + }, ++ { ++ "<script>var tmpl = `asd {{.}}`;</script>", ++ `{{.}} appears in a JS template literal`, ++ }, + } + for _, test := range tests { + buf := new(bytes.Buffer) +@@ -1280,6 +1284,10 @@ func TestEscapeText(t *testing.T) { + context{state: stateJSSqStr, delim: delimDoubleQuote, attr: attrScript}, + }, + { ++ "<a onclick=\"`foo", ++ context{state: stateJSBqStr, delim: delimDoubleQuote, attr: attrScript}, ++ }, ++ { + `<A ONCLICK="'`, + context{state: stateJSSqStr, delim: delimDoubleQuote, attr: attrScript}, + }, +diff --git a/src/html/template/js.go b/src/html/template/js.go +index ea9c183..b888eaf 100644 +--- a/src/html/template/js.go ++++ b/src/html/template/js.go +@@ -308,6 +308,7 @@ var jsStrReplacementTable = []string{ + // Encode HTML specials as hex so the output can be embedded + // in HTML attributes without further encoding. + '"': `\u0022`, ++ '`': `\u0060`, + '&': `\u0026`, + '\'': `\u0027`, + '+': `\u002b`, +@@ -331,6 +332,7 @@ var jsStrNormReplacementTable = []string{ + '"': `\u0022`, + '&': `\u0026`, + '\'': `\u0027`, ++ '`': `\u0060`, + '+': `\u002b`, + '/': `\/`, + '<': `\u003c`, +diff --git a/src/html/template/js_test.go b/src/html/template/js_test.go +index d7ee47b..7d963ae 100644 +--- a/src/html/template/js_test.go ++++ b/src/html/template/js_test.go +@@ -292,7 +292,7 @@ func TestEscapersOnLower7AndSelectHighCodepoints(t *testing.T) { + `0123456789:;\u003c=\u003e?` + + `@ABCDEFGHIJKLMNO` + + `PQRSTUVWXYZ[\\]^_` + +- "`abcdefghijklmno" + ++ "\\u0060abcdefghijklmno" + + "pqrstuvwxyz{|}~\u007f" + + "\u00A0\u0100\\u2028\\u2029\ufeff\U0001D11E", + }, +diff --git a/src/html/template/jsctx_string.go b/src/html/template/jsctx_string.go +index dd1d87e..2394893 100644 +--- a/src/html/template/jsctx_string.go ++++ b/src/html/template/jsctx_string.go +@@ -4,6 +4,15 @@ package template + + import "strconv" + ++func _() { ++ // An "invalid array index" compiler error signifies that the constant values have changed. ++ // Re-run the stringer command to generate them again. ++ var x [1]struct{} ++ _ = x[jsCtxRegexp-0] ++ _ = x[jsCtxDivOp-1] ++ _ = x[jsCtxUnknown-2] ++} ++ + const _jsCtx_name = "jsCtxRegexpjsCtxDivOpjsCtxUnknown" + + var _jsCtx_index = [...]uint8{0, 11, 21, 33} +diff --git a/src/html/template/state_string.go b/src/html/template/state_string.go +index 05104be..6fb1a6e 100644 +--- a/src/html/template/state_string.go ++++ b/src/html/template/state_string.go +@@ -4,9 +4,42 @@ package template + + import "strconv" + +-const _state_name = "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateError" ++func _() { ++ // An "invalid array index" compiler error signifies that the constant values have changed. ++ // Re-run the stringer command to generate them again. ++ var x [1]struct{} ++ _ = x[stateText-0] ++ _ = x[stateTag-1] ++ _ = x[stateAttrName-2] ++ _ = x[stateAfterName-3] ++ _ = x[stateBeforeValue-4] ++ _ = x[stateHTMLCmt-5] ++ _ = x[stateRCDATA-6] ++ _ = x[stateAttr-7] ++ _ = x[stateURL-8] ++ _ = x[stateSrcset-9] ++ _ = x[stateJS-10] ++ _ = x[stateJSDqStr-11] ++ _ = x[stateJSSqStr-12] ++ _ = x[stateJSBqStr-13] ++ _ = 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] ++} ++ ++const _state_name = "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSBqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateErrorstateDead" + +-var _state_index = [...]uint16{0, 9, 17, 30, 44, 60, 72, 83, 92, 100, 111, 118, 130, 142, 155, 170, 184, 192, 205, 218, 231, 244, 255, 271, 286, 296} ++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} + + 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 06df679..92eb351 100644 +--- a/src/html/template/transition.go ++++ b/src/html/template/transition.go +@@ -27,6 +27,7 @@ var transitionFunc = [...]func(context, []byte) (context, int){ + stateJS: tJS, + stateJSDqStr: tJSDelimited, + stateJSSqStr: tJSDelimited, ++ stateJSBqStr: tJSDelimited, + stateJSRegexp: tJSDelimited, + stateJSBlockCmt: tBlockCmt, + stateJSLineCmt: tLineCmt, +@@ -262,7 +263,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) +@@ -274,6 +275,8 @@ func tJS(c context, s []byte) (context, int) { + c.state, c.jsCtx = stateJSDqStr, jsCtxRegexp + case '\'': + c.state, c.jsCtx = stateJSSqStr, jsCtxRegexp ++ case '`': ++ c.state, c.jsCtx = stateJSBqStr, jsCtxRegexp + case '/': + switch { + case i+1 < len(s) && s[i+1] == '/': +@@ -303,6 +306,8 @@ func tJSDelimited(c context, s []byte) (context, int) { + switch c.state { + case stateJSSqStr: + specials = `\'` ++ case stateJSBqStr: ++ specials = "`\\" + case stateJSRegexp: + specials = `\/[]` + } +-- +2.7.4 -- 2.7.4
-=-=-=-=-=-=-=-=-=-=-=- Links: You receive all messages sent to this group. View/Reply Online (#180338): https://lists.openembedded.org/g/openembedded-core/message/180338 Mute This Topic: https://lists.openembedded.org/mt/98464668/21656 Group Owner: openembedded-core+ow...@lists.openembedded.org Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-