unicode/norm: correct use of ErrShortDst In some cases the ErrShortDst error was eroneously overriden by ErrShortSrc. Fixes golang/go#24170. Change-Id: I07dd160de045474e8e38506b6793a1da0df6283d Reviewed-on: https://go-review.googlesource.com/c/145558 Run-TryBot: Marcel van Lohuizen <mpvl@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ross Light <light@google.com>
diff --git a/unicode/norm/transform.go b/unicode/norm/transform.go index 9f47efb..a1d366a 100644 --- a/unicode/norm/transform.go +++ b/unicode/norm/transform.go
@@ -18,7 +18,6 @@ // Users should either catch ErrShortDst and allow dst to grow or have dst be at // least of size MaxTransformChunkSize to be guaranteed of progress. func (f Form) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { - n := 0 // Cap the maximum number of src bytes to check. b := src eof := atEOF @@ -27,13 +26,14 @@ eof = false b = b[:ns] } - i, ok := formTable[f].quickSpan(inputBytes(b), n, len(b), eof) - n += copy(dst[n:], b[n:i]) + i, ok := formTable[f].quickSpan(inputBytes(b), 0, len(b), eof) + n := copy(dst, b[:i]) if !ok { nDst, nSrc, err = f.transform(dst[n:], src[n:], atEOF) return nDst + n, nSrc + n, err } - if n < len(src) && !atEOF { + + if err == nil && n < len(src) && !atEOF { err = transform.ErrShortSrc } return n, n, err @@ -79,7 +79,7 @@ nSrc += n nDst += n if ok { - if n < rb.nsrc && !atEOF { + if err == nil && n < rb.nsrc && !atEOF { err = transform.ErrShortSrc } return nDst, nSrc, err
diff --git a/unicode/norm/transform_test.go b/unicode/norm/transform_test.go index d596ff3..2690fc3 100644 --- a/unicode/norm/transform_test.go +++ b/unicode/norm/transform_test.go
@@ -47,6 +47,13 @@ {NFD, "a\u0300", "", false, 4, transform.ErrShortSrc}, {NFC, "ö", "", false, 3, transform.ErrShortSrc}, + {NFD, "abc", "", false, 1, transform.ErrShortDst}, + {NFC, "abc", "", false, 1, transform.ErrShortDst}, + {NFC, "abc", "a", false, 2, transform.ErrShortDst}, + {NFD, "éfff", "", false, 2, transform.ErrShortDst}, + {NFC, "e\u0301fffff", "\u00e9fff", false, 6, transform.ErrShortDst}, + {NFD, "ééééé", "e\u0301e\u0301e\u0301", false, 15, transform.ErrShortDst}, + {NFC, "a\u0300", "", true, 1, transform.ErrShortDst}, // Theoretically could fit, but won't due to simplified checks. {NFC, "a\u0300", "", true, 2, transform.ErrShortDst}, @@ -62,14 +69,16 @@ } b := make([]byte, 100) for i, tt := range tests { - nDst, _, err := tt.f.Transform(b[:tt.dstSize], []byte(tt.in), tt.eof) - out := string(b[:nDst]) - if out != tt.out || err != tt.err { - t.Errorf("%d: was %+q (%v); want %+q (%v)", i, out, err, tt.out, tt.err) - } - if want := tt.f.String(tt.in)[:nDst]; want != out { - t.Errorf("%d: incorrect normalization: was %+q; want %+q", i, out, want) - } + t.Run(fmt.Sprintf("%d:%s", i, tt.in), func(t *testing.T) { + nDst, _, err := tt.f.Transform(b[:tt.dstSize], []byte(tt.in), tt.eof) + out := string(b[:nDst]) + if out != tt.out || err != tt.err { + t.Errorf("was %+q (%v); want %+q (%v)", out, err, tt.out, tt.err) + } + if want := tt.f.String(tt.in)[:nDst]; want != out { + t.Errorf("incorrect normalization: was %+q; want %+q", out, want) + } + }) } }