bpo-24214: Fixed the UTF-8 and UTF-16 incremental decoders. (GH-14304)
* The UTF-8 incremental decoders fails now fast if encounter
a sequence that can't be handled by the error handler.
* The UTF-16 incremental decoders with the surrogatepass error
handler decodes now a lone low surrogate with final=False.
diff --git a/Objects/stringlib/codecs.h b/Objects/stringlib/codecs.h
index 8645bc2..d6f2b98 100644
--- a/Objects/stringlib/codecs.h
+++ b/Objects/stringlib/codecs.h
@@ -207,7 +207,7 @@
goto InvalidContinuation1;
} else if (ch == 0xF4 && ch2 >= 0x90) {
/* invalid sequence
- \xF4\x90\x80\80- -- 110000- overflow */
+ \xF4\x90\x80\x80- -- 110000- overflow */
goto InvalidContinuation1;
}
if (!IS_CONTINUATION_BYTE(ch3)) {
@@ -573,10 +573,10 @@
}
/* UTF-16 code pair: */
- if (q >= e)
- goto UnexpectedEnd;
if (!Py_UNICODE_IS_HIGH_SURROGATE(ch))
goto IllegalEncoding;
+ if (q >= e)
+ goto UnexpectedEnd;
ch2 = (q[ihi] << 8) | q[ilo];
q += 2;
if (!Py_UNICODE_IS_LOW_SURROGATE(ch2))
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 625be4b..cb1456e 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -4945,11 +4945,15 @@
endinpos = startinpos + 1;
break;
case 2:
- case 3:
- case 4:
- if (s == end || consumed) {
+ if (consumed && (unsigned char)s[0] == 0xED && end - s == 2
+ && (unsigned char)s[1] >= 0xA0 && (unsigned char)s[1] <= 0xBF)
+ {
+ /* Truncated surrogate code in range D800-DFFF */
goto End;
}
+ /* fall through */
+ case 3:
+ case 4:
errmsg = "invalid continuation byte";
startinpos = s - starts;
endinpos = startinpos + ch - 1;