internal/export/idna: avoid memory leak in validation codes These functions have same issues. * validateRegistration * validateAndMap * validateFromPunycode When string does not hold enough bytes, lookupString will return 0 for the size. In this case, we should raise runeError. This is the way that we can avoid infinite loop. Fixes: golang/go#22184 Change-Id: I068e4cc9919777468922deed5d7a427996e0ad61 Reviewed-on: https://go-review.googlesource.com/73730 Run-TryBot: Marcel van Lohuizen <mpvl@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/internal/export/idna/idna.go b/internal/export/idna/idna.go index 9feea64..fd8f3bd 100644 --- a/internal/export/idna/idna.go +++ b/internal/export/idna/idna.go
@@ -405,6 +405,9 @@ } for i := 0; i < len(s); { v, sz := trie.lookupString(s[i:]) + if sz == 0 { + return s, bidi, runeError(utf8.RuneError) + } bidi = bidi || info(v).isBidi(s[i:]) // Copy bytes not copied so far. switch p.simplify(info(v).category()) { @@ -446,6 +449,15 @@ var combinedInfoBits info 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 + } combinedInfoBits |= info(v) bidi = bidi || info(v).isBidi(s[i:]) start := i @@ -584,6 +596,9 @@ // loop. 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/idna_test.go b/internal/export/idna/idna_test.go index fed6e2e..ff878e5 100644 --- a/internal/export/idna/idna_test.go +++ b/internal/export/idna/idna_test.go
@@ -167,6 +167,7 @@ {resolve, "\u3002b", ".b", ""}, {resolve, "..b", "..b", ""}, {resolve, "b..", "b..", ""}, + {resolve, "\xed", "", "P1"}, // Raw punycode {punyA, "", "", ""},