11package software .amazon .event .ruler ;
22
3- import software .amazon .event .ruler .input .InputByte ;
4- import software .amazon .event .ruler .input .InputCharacter ;
5- import software .amazon .event .ruler .input .InputCharacterType ;
6- import software .amazon .event .ruler .input .InputMultiByteSet ;
7- import software .amazon .event .ruler .input .MultiByte ;
8-
9- import javax .annotation .concurrent .ThreadSafe ;
103import java .nio .charset .StandardCharsets ;
114import java .util .AbstractMap ;
125import java .util .ArrayDeque ;
2013import java .util .concurrent .ConcurrentHashMap ;
2114import java .util .concurrent .atomic .AtomicInteger ;
2215
16+ import javax .annotation .concurrent .ThreadSafe ;
17+
2318import static software .amazon .event .ruler .CompoundByteTransition .coalesce ;
2419import static software .amazon .event .ruler .MatchType .ANYTHING_BUT_SUFFIX ;
2520import static software .amazon .event .ruler .MatchType .EQUALS_IGNORE_CASE ;
2823import static software .amazon .event .ruler .MatchType .SUFFIX ;
2924import static software .amazon .event .ruler .MatchType .SUFFIX_EQUALS_IGNORE_CASE ;
3025import static software .amazon .event .ruler .input .DefaultParser .getParser ;
26+ import software .amazon .event .ruler .input .InputByte ;
27+ import software .amazon .event .ruler .input .InputCharacter ;
28+ import software .amazon .event .ruler .input .InputCharacterType ;
29+ import software .amazon .event .ruler .input .InputMultiByteSet ;
30+ import software .amazon .event .ruler .input .MultiByte ;
3131import static software .amazon .event .ruler .input .MultiByte .MAX_CONTINUATION_BYTE ;
3232import static software .amazon .event .ruler .input .MultiByte .MAX_FIRST_BYTE_FOR_ONE_BYTE_CHAR ;
3333import static software .amazon .event .ruler .input .MultiByte .MAX_FIRST_BYTE_FOR_TWO_BYTE_CHAR ;
@@ -877,7 +877,14 @@ private boolean isNextCharacterFirstContinuationByteForSuffixMatch(InputCharacte
877877 }
878878
879879 private boolean isContinuationByte (InputCharacter [] characters , int i ) {
880- if (i < 0 ) {
880+ if (i < 0 || i >= characters .length ) {
881+ return false ;
882+ }
883+ // Wildcard sentinels (and any other non-byte InputCharacter) are not
884+ // continuation bytes. They mark the end of any multi-byte sequence
885+ // being walked, so forward/backward walkers must stop here rather
886+ // than attempting to cast to InputByte.
887+ if (!isByte (characters [i ])) {
881888 return false ;
882889 }
883890 byte continuationByte = InputByte .cast (characters [i ]).getByte ();
@@ -896,6 +903,12 @@ private String extractNextJavaCharacterFromInputCharacters(InputCharacter[] char
896903 private String extractNextJavaCharacterFromInputCharactersForBackwardsArrays (InputCharacter [] characters , int i ) {
897904 List <Byte > bytesList = new ArrayList <>();
898905 for (int multiByteIndex = i ; multiByteIndex < characters .length ; multiByteIndex ++) {
906+ // If we reach a non-byte InputCharacter (e.g. InputWildcard at the
907+ // trailing '*' of a wildcard pattern), the multi-byte sequence has
908+ // already ended. Stop before casting to InputByte.
909+ if (!isByte (characters [multiByteIndex ])) {
910+ break ;
911+ }
899912 if (!isContinuationByte (characters , multiByteIndex )) {
900913 // This is the last byte of the suffix char
901914 bytesList .add (InputByte .cast (characters [multiByteIndex ]).getByte ());
0 commit comments