Possible ClassCastException in java.util.regex.Pattern.BmpCharPredicate#union(java.util.regex.Pattern.CharPredicate...)

Stuart Marks stuart.marks at oracle.com
Sat Sep 4 00:32:01 UTC 2021


Yeah, not only does this static union() method seem like dead code, it seems wrong 
as well. Perhaps igraves should take a look at this.

The whole area seems suspicious. There doesn't seem to be any semantic difference 
between BmpCharPredicate and CharPredicate. The and() & union() combinators 
preserve class: combining BmpCharPredicates gives a BmpCharPredicate, otherwise a 
CharPredicate. But evaluating one versus the other doesn't seem to make a 
difference. However, there are a couple instanceof checks that change logic paths in 
places where they're used... urghhh....

s'marks


On 8/27/21 8:37 AM, Pavel Rappo wrote:
> Has that method been ever used? If nothing else its name seems strange. To me, a union has OR semantics, not AND.
> 
>> On 27 Aug 2021, at 15:37, Andrey Turbanov <turbanoff at gmail.com> wrote:
>>
>> Hello.
>> I found suspicious code in the method
>> "java.util.regex.Pattern.BmpCharPredicate#union(java.util.regex.Pattern.CharPredicate...)"
>> https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/util/regex/Pattern.java#L5639
>>
>> static CharPredicate union(CharPredicate... predicates) {
>>     CharPredicate cp = ch -> {
>>         for (CharPredicate p : predicates) {
>>             if (!p.is(ch))
>>                 return false;
>>         }
>>         return true;
>>     };
>>     for (CharPredicate p : predicates) {
>>         if (! (p instanceof BmpCharPredicate))
>>             return cp;
>>     }
>>     return (BmpCharPredicate)cp;
>> }
>>
>> Variable `cp` has type CharPredicate initially. And then it's casted
>> to BmpCharPredicate. This cast always fails with ClassCastException
>> when reached.
>>
>> Can reproduced in small sample class:
>>
>>     public static void main(String[] args) {
>>         CharPredicate result = BmpCharPredicate.union();
>>         System.out.println(result);
>>     }
>>
>>     interface CharPredicate {
>>         boolean is(int ch);
>>     }
>>
>>     interface BmpCharPredicate extends CharPredicate {
>>         static CharPredicate union(CharPredicate... predicates) {
>>             CharPredicate cp = ch -> true;
>>             for (CharPredicate p : predicates) {
>>                 if (! (p instanceof BmpCharPredicate))
>>                     return cp;
>>             }
>>             return (BmpCharPredicate)cp;
>>         }
>>     }
>>
>>
>> Exception in thread "main" java.lang.ClassCastException: class
>> org.RegexpBug$BmpCharPredicate$$Lambda$14/0x0000000800c028f0 cannot be
>> cast to class org.RegexpBug$BmpCharPredicate
>> (org.RegexpBug$BmpCharPredicate$$Lambda$14/0x0000000800c028f0 and
>> org.RegexpBug$BmpCharPredicate are in unnamed module of loader 'app')
>>     at org.RegexpBug$BmpCharPredicate.union(RegexpBug.java:20)
>>     at org.RegexpBug.main(RegexpBug.java:5)
>>
>> As I can see this method is never used. Perhaps it should be removed?
>>
>>
>> Andrey Turbanov
> 


More information about the core-libs-dev mailing list