|
8 | 8 | * return c >= 97 && c <= 122;
|
9 | 9 | * }
|
10 | 10 | * ```
|
| 11 | + * |
| 12 | + * @kind problem |
| 13 | + * @id TODO |
11 | 14 | */
|
12 | 15 |
|
13 | 16 | import java
|
14 | 17 | import semmle.code.java.Conversions
|
15 | 18 |
|
| 19 | +predicate isUsedAsChar(IntegerLiteral intLiteral) { |
| 20 | + intLiteral.(ConversionSite).getConversionTarget() instanceof CharacterType and |
| 21 | + // Ignore if used in arithmetic operation; probably only have to consider AssignOp (e.g. `+=`) because for |
| 22 | + // other arithmetic operations implicit conversion to greater numeric type (e.g. `int`) occurs (?) |
| 23 | + not any(AssignOp a).getRhs() = intLiteral |
| 24 | + or |
| 25 | + // Or comparing with a char value |
| 26 | + exists(BinaryExpr comp | |
| 27 | + comp instanceof EqualityTest |
| 28 | + or |
| 29 | + comp instanceof ComparisonExpr and |
| 30 | + // But only consider when comparing with an alpha-numeric char (a-z, A-Z, 0-9) |
| 31 | + // Control code checks such as `c < 0x20` might be easier to understand than `c < ' '` |
| 32 | + exists(int codePoint | codePoint = intLiteral.getIntValue() | |
| 33 | + codePoint = [97 .. 122] or codePoint = [65 .. 90] or codePoint = [48 .. 57] |
| 34 | + ) |
| 35 | + | |
| 36 | + comp.getAnOperand() = intLiteral and comp.getAnOperand().getType() instanceof CharacterType |
| 37 | + ) |
| 38 | + or |
| 39 | + // Or calling `Character.equals` |
| 40 | + exists(MethodAccess equalsCall | |
| 41 | + equalsCall.getMethod() instanceof EqualsMethod and |
| 42 | + equalsCall.getQualifier().getType().(RefType).hasQualifiedName("java.lang", "Character") and |
| 43 | + equalsCall.getArgument(0) = intLiteral |
| 44 | + ) |
| 45 | +} |
| 46 | + |
16 | 47 | from IntegerLiteral intLiteral, int codePoint, string asciiChar
|
17 | 48 | where
|
18 |
| - intLiteral.(ConversionSite).getConversionTarget() instanceof CharacterType |
19 |
| - and codePoint = intLiteral.getIntValue() |
20 |
| - and codePoint in [32 .. 126] |
21 |
| - and asciiChar = codePoint.toUnicode() |
22 |
| -select intLiteral, "Uses int literal instead of char literal for printable ASCII char '" + asciiChar + "'" |
| 49 | + isUsedAsChar(intLiteral) and |
| 50 | + codePoint = intLiteral.getIntValue() and |
| 51 | + codePoint in [32 .. 126] and |
| 52 | + asciiChar = codePoint.toUnicode() |
| 53 | +select intLiteral, |
| 54 | + "Uses int literal instead of char literal for printable ASCII char '" + asciiChar + "'" |
0 commit comments