@@ -1044,6 +1044,58 @@ def mutating(exc):
10441044 for (encoding , data ) in baddata :
10451045 self .assertEqual (data .decode (encoding , "test.mutating" ), "\u4242 " )
10461046
1047+ # issue32583
1048+ def test_crashing_decode_handler (self ):
1049+ # better generating one more character to fill the extra space slot
1050+ # so in debug build it can steadily fail
1051+ def forward_shorter_than_end (exc ):
1052+ if isinstance (exc , UnicodeDecodeError ):
1053+ # size one character, 0 < forward < exc.end
1054+ return ('\ufffd ' , exc .start + 1 )
1055+ else :
1056+ raise TypeError ("don't know how to handle %r" % exc )
1057+ codecs .register_error (
1058+ "test.forward_shorter_than_end" , forward_shorter_than_end )
1059+
1060+ self .assertEqual (
1061+ b'\xd8 \xd8 \xd8 \xd8 \xd8 \x00 \x00 \x00 ' .decode (
1062+ 'utf-16-le' , 'test.forward_shorter_than_end' ),
1063+ '\ufffd \ufffd \ufffd \ufffd \xd8 \x00 '
1064+ )
1065+ self .assertEqual (
1066+ b'\xd8 \xd8 \xd8 \xd8 \x00 \xd8 \x00 \x00 ' .decode (
1067+ 'utf-16-be' , 'test.forward_shorter_than_end' ),
1068+ '\ufffd \ufffd \ufffd \ufffd \xd8 \x00 '
1069+ )
1070+ self .assertEqual (
1071+ b'\x11 \x11 \x11 \x11 \x11 \x00 \x00 \x00 \x00 \x00 \x00 ' .decode (
1072+ 'utf-32-le' , 'test.forward_shorter_than_end' ),
1073+ '\ufffd \ufffd \ufffd \u1111 \x00 '
1074+ )
1075+ self .assertEqual (
1076+ b'\x11 \x11 \x11 \x00 \x00 \x11 \x11 \x00 \x00 \x00 \x00 ' .decode (
1077+ 'utf-32-be' , 'test.forward_shorter_than_end' ),
1078+ '\ufffd \ufffd \ufffd \u1111 \x00 '
1079+ )
1080+
1081+ def replace_with_long (exc ):
1082+ if isinstance (exc , UnicodeDecodeError ):
1083+ exc .object = b"\x00 " * 8
1084+ return ('\ufffd ' , exc .start )
1085+ else :
1086+ raise TypeError ("don't know how to handle %r" % exc )
1087+ codecs .register_error ("test.replace_with_long" , replace_with_long )
1088+
1089+ self .assertEqual (
1090+ b'\x00 ' .decode ('utf-16' , 'test.replace_with_long' ),
1091+ '\ufffd \x00 \x00 \x00 \x00 '
1092+ )
1093+ self .assertEqual (
1094+ b'\x00 ' .decode ('utf-32' , 'test.replace_with_long' ),
1095+ '\ufffd \x00 \x00 '
1096+ )
1097+
1098+
10471099 def test_fake_error_class (self ):
10481100 handlers = [
10491101 codecs .strict_errors ,
0 commit comments