From efb744f6d9f03fc4b427c774f83540712ac8e8dc Mon Sep 17 00:00:00 2001 From: Timothy Gu Date: Thu, 4 Nov 2021 18:42:52 -0700 Subject: [PATCH] internal/export/idna: fix infinite loop in Go pre-1.10 lookupString returns 0 for incomplete UTF-8 sequences, so to prevent infinite loops we must specifically check for that case. However, CL 73730 which fixed this issue in 2017 was lost in the shuffle that allowed multiple Unicode versions in x/text (CL 83235), and the fix was never applied to idna9.0.0.go. This CL fixes that oversight. Updates golang/go#22184 Change-Id: I3a6ab08b157f4017560020ff259d1afbe49a9e71 Reviewed-on: https://go-review.googlesource.com/c/text/+/361494 Reviewed-by: Damien Neil TryBot-Result: Gopher Robot Run-TryBot: Ian Lance Taylor Reviewed-by: David Chase Reviewed-by: Marcel van Lohuizen --- internal/export/idna/idna9.0.0.go | 17 ++++++++++++++++- internal/export/idna/idna9.0.0_test.go | 1 + 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/internal/export/idna/idna9.0.0.go b/internal/export/idna/idna9.0.0.go index 96424a0b..f217b1a4 100644 --- a/internal/export/idna/idna9.0.0.go +++ b/internal/export/idna/idna9.0.0.go @@ -197,7 +197,7 @@ type options struct { bidirule func(s string) bool } -// A Profile defines the configuration of a IDNA mapper. +// A Profile defines the configuration of an IDNA mapper. type Profile struct { options } @@ -426,6 +426,9 @@ func validateRegistration(p *Profile, s string) (string, error) { } for i := 0; i < len(s); { v, sz := trie.lookupString(s[i:]) + if sz == 0 { + return s, runeError(utf8.RuneError) + } // Copy bytes not copied so far. switch p.simplify(info(v).category()) { // TODO: handle the NV8 defined in the Unicode idna data set to allow @@ -448,6 +451,15 @@ func validateAndMap(p *Profile, s string) (string, error) { ) for i := 0; i < len(s); { v, sz := trie.lookupString(s[i:]) + if sz == 0 { + b = append(b, s[k:i]...) + b = append(b, "\ufffd"...) + k = len(s) + if err == nil { + err = runeError(utf8.RuneError) + } + break + } start := i i += sz // Copy bytes not copied so far. @@ -580,6 +592,9 @@ func validateFromPunycode(p *Profile, s string) error { } for i := 0; i < len(s); { v, sz := trie.lookupString(s[i:]) + if sz == 0 { + return runeError(utf8.RuneError) + } if c := p.simplify(info(v).category()); c != valid && c != deviation { return &labelError{s, "V6"} } diff --git a/internal/export/idna/idna9.0.0_test.go b/internal/export/idna/idna9.0.0_test.go index 524727b1..91a1e90d 100644 --- a/internal/export/idna/idna9.0.0_test.go +++ b/internal/export/idna/idna9.0.0_test.go @@ -78,6 +78,7 @@ func TestLabelErrors(t *testing.T) { {resolve, "\u3002b", "b", ""}, {resolve, "..b", "b", ""}, {resolve, "b..", "b..", ""}, + {resolve, "\xed", "", "P1"}, // Raw punycode {punyA, "", "", ""},