]> Cypherpunks repositories - gostls13.git/commitdiff
strconv: reject surrogate halves in Unquote
authorJoe Tsai <joetsai@digital-static.net>
Fri, 20 Aug 2021 19:50:02 +0000 (12:50 -0700)
committerJoe Tsai <joetsai@digital-static.net>
Sat, 21 Aug 2021 18:23:58 +0000 (18:23 +0000)
Unquote implements unescaping a "single-quoted, doubled-quoted, or
backquoted Go string literal". Therefore, it should reject anything
that the Go specification explicitly forbids.

The section on "Rune literals" explicitly rejects rune values
"above 0x10FFFF and surrogate halves". We properly checked for
the previous condition, but were failing to check for the latter.

In general, "r > utf8.MaxRune" is probably the wrong check,
while !utf8.ValidRune(r) is the more correct check.
We make changes to both UnquoteChar and appendEscapedRune
to use the correct check. The change to appendEscapedRune
is technically a noop since callers of that function already
guarantee that the provided rune is valid.

Fixes #47853

Change-Id: Ib8977e56b91943ec8ada821b8d217b5e9a66f950
Reviewed-on: https://go-review.googlesource.com/c/go/+/343877
Trust: Joe Tsai <joetsai@digital-static.net>
Run-TryBot: Joe Tsai <joetsai@digital-static.net>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Rob Pike <r@golang.org>
src/strconv/quote.go
src/strconv/quote_test.go

index b3bbb1612b9f634e930fc169bc329e87d1c8858d..d2814b92da795b77ceb1a4757748cf7d25ca6ea2 100644 (file)
@@ -103,7 +103,7 @@ func appendEscapedRune(buf []byte, r rune, quote byte, ASCIIonly, graphicOnly bo
                        buf = append(buf, `\x`...)
                        buf = append(buf, lowerhex[byte(r)>>4])
                        buf = append(buf, lowerhex[byte(r)&0xF])
-               case r > utf8.MaxRune:
+               case !utf8.ValidRune(r):
                        r = 0xFFFD
                        fallthrough
                case r < 0x10000:
@@ -322,7 +322,7 @@ func UnquoteChar(s string, quote byte) (value rune, multibyte bool, tail string,
                        value = v
                        break
                }
-               if v > utf8.MaxRune {
+               if !utf8.ValidRune(v) {
                        err = ErrSyntax
                        return
                }
index 4750be27408a65dfd4c2f51864abda3862d60250..81fc8f79e147499f14798d1831bb8d61d6b55ce2 100644 (file)
@@ -131,6 +131,7 @@ var quoterunetests = []quoteRuneTest{
        {'\\', `'\\'`, `'\\'`, `'\\'`},
        {0xFF, `'ÿ'`, `'\u00ff'`, `'ÿ'`},
        {0x263a, `'☺'`, `'\u263a'`, `'☺'`},
+       {0xdead, `'�'`, `'\ufffd'`, `'�'`},
        {0xfffd, `'�'`, `'\ufffd'`, `'�'`},
        {0x0010ffff, `'\U0010ffff'`, `'\U0010ffff'`, `'\U0010ffff'`},
        {0x0010ffff + 1, `'�'`, `'\ufffd'`, `'�'`},
@@ -305,6 +306,8 @@ var misquoted = []string{
        "\"\n\"",
        "\"\\n\n\"",
        "'\n'",
+       `"\udead"`,
+       `"\ud83d\ude4f"`,
 }
 
 func TestUnquote(t *testing.T) {