Skip to content

Commit 58d2d5d

Browse files
Marcono1234smowton
authored andcommitted
Java: Replace incorrect usage of Literal.getLiteral()
1 parent 1c1c465 commit 58d2d5d

File tree

10 files changed

+47
-51
lines changed

10 files changed

+47
-51
lines changed

java/ql/lib/semmle/code/java/Annotation.qll

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,7 @@ class Annotatable extends Element {
118118
* annotation attached to it for the specified `category`.
119119
*/
120120
predicate suppressesWarningsAbout(string category) {
121-
exists(string withQuotes |
122-
withQuotes = getAnAnnotation().(SuppressWarningsAnnotation).getASuppressedWarning()
123-
|
124-
category = withQuotes.substring(1, withQuotes.length() - 1)
125-
)
121+
category = getAnAnnotation().(SuppressWarningsAnnotation).getASuppressedWarning()
126122
or
127123
this.(Member).getDeclaringType().suppressesWarningsAbout(category)
128124
or

java/ql/lib/semmle/code/java/Expr.qll

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -599,10 +599,23 @@ class AssignURShiftExpr extends AssignOp, @assignurshiftexpr {
599599

600600
/** A common super-class to represent constant literals. */
601601
class Literal extends Expr, @literal {
602-
/** Gets a string representation of this literal. */
602+
/**
603+
* Gets a string representation of this literal as it appeared
604+
* in the source code.
605+
*
606+
* **Important:** Unless a query explicitly wants to check how
607+
* a literal was written in the source code, the predicate
608+
* `getValue()` (or value predicates of subclasses) should be
609+
* used instead. For example for the integer literal `0x7fff_ffff`
610+
* the result of `getLiteral()` would be `0x7fff_ffff`, while
611+
* the result of `getValue()` would be `2147483647`.
612+
*/
603613
string getLiteral() { namestrings(result, _, this) }
604614

605-
/** Gets a string representation of the value of this literal. */
615+
/**
616+
* Gets a string representation of the value this literal
617+
* represents.
618+
*/
606619
string getValue() { namestrings(_, result, this) }
607620

608621
/** Gets a printable representation of this expression. */
@@ -619,9 +632,9 @@ class Literal extends Expr, @literal {
619632
class BooleanLiteral extends Literal, @booleanliteral {
620633
/** Gets the boolean representation of this literal. */
621634
boolean getBooleanValue() {
622-
result = true and getLiteral() = "true"
635+
result = true and getValue() = "true"
623636
or
624-
result = false and getLiteral() = "false"
637+
result = false and getValue() = "false"
625638
}
626639

627640
override string getAPrimaryQlClass() { result = "BooleanLiteral" }

java/ql/lib/semmle/code/java/JDKAnnotations.qll

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,7 @@ class SuppressWarningsAnnotation extends Annotation {
2525
}
2626

2727
/** Gets the name of a warning suppressed by this annotation. */
28-
string getASuppressedWarning() {
29-
result = this.getAValue().(StringLiteral).getLiteral() or
30-
result = this.getAValue().(ArrayInit).getAnInit().(StringLiteral).getLiteral()
31-
}
28+
string getASuppressedWarning() { result = getASuppressedWarningLiteral().getRepresentedString() }
3229
}
3330

3431
/** A `@Target` annotation. */

java/ql/lib/semmle/code/java/security/RelativePaths.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import java
55
* An element that starts with a relative path.
66
*/
77
predicate relativePath(Element tree, string command) {
8-
exists(StringLiteral lit, string text | tree = lit and text = lit.getLiteral() |
8+
exists(StringLiteral lit, string text | tree = lit and text = lit.getRepresentedString() |
99
text != "" and
1010
(
1111
text.regexpMatch("[^/\\\\ \t]*") or

java/ql/src/Likely Bugs/Collections/WriteOnlyContainer.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ where
2424
// Exclude fields that may be read from reflectively.
2525
not reflectivelyRead(v) and
2626
// Exclude fields annotated with `@SuppressWarnings("unused")`.
27-
not v.getAnAnnotation().(SuppressWarningsAnnotation).getASuppressedWarning() = "\"unused\"" and
27+
not v.getAnAnnotation().(SuppressWarningsAnnotation).getASuppressedWarning() = "unused" and
2828
// Exclude fields with relevant Lombok annotations.
2929
not v instanceof LombokGetterAnnotatedField and
3030
// Every access to `v` is either...

java/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.ql

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ import DataFlow
1717
import PathGraph
1818

1919
private class ShortStringLiteral extends StringLiteral {
20-
ShortStringLiteral() { getLiteral().length() < 100 }
20+
ShortStringLiteral() { getRepresentedString().length() < 100 }
2121
}
2222

2323
class BrokenAlgoLiteral extends ShortStringLiteral {
2424
BrokenAlgoLiteral() {
25-
getValue().regexpMatch(getInsecureAlgorithmRegex()) and
25+
getRepresentedString().regexpMatch(getInsecureAlgorithmRegex()) and
2626
// Exclude German and French sentences.
27-
not getValue().regexpMatch(".*\\p{IsLowercase} des \\p{IsLetter}.*")
27+
not getRepresentedString().regexpMatch(".*\\p{IsLowercase} des \\p{IsLetter}.*")
2828
}
2929
}
3030

@@ -48,4 +48,4 @@ where
4848
source.getNode().asExpr() = s and
4949
conf.hasFlowPath(source, sink)
5050
select c, source, sink, "Cryptographic algorithm $@ is weak and should not be used.", s,
51-
s.getLiteral()
51+
s.getRepresentedString()

java/ql/src/Security/CWE/CWE-327/MaybeBrokenCryptoAlgorithm.ql

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@ import semmle.code.java.dispatch.VirtualDispatch
1818
import PathGraph
1919

2020
private class ShortStringLiteral extends StringLiteral {
21-
ShortStringLiteral() { getLiteral().length() < 100 }
21+
ShortStringLiteral() { getRepresentedString().length() < 100 }
2222
}
2323

2424
class InsecureAlgoLiteral extends ShortStringLiteral {
2525
InsecureAlgoLiteral() {
2626
// Algorithm identifiers should be at least two characters.
27-
getValue().length() > 1 and
28-
exists(string s | s = getLiteral() |
27+
getRepresentedString().length() > 1 and
28+
exists(string s | s = getRepresentedString() |
2929
not s.regexpMatch(getSecureAlgorithmRegex()) and
3030
// Exclude results covered by another query.
3131
not s.regexpMatch(getInsecureAlgorithmRegex())
@@ -72,4 +72,4 @@ where
7272
conf.hasFlowPath(source, sink)
7373
select c, source, sink,
7474
"Cryptographic algorithm $@ may not be secure, consider using a different algorithm.", s,
75-
s.getLiteral()
75+
s.getRepresentedString()

java/ql/src/Violations of Best Practice/Magic Constants/MagicConstants.qll

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -186,24 +186,21 @@ private predicate trivialIntValue(string s) {
186186
exists(string pos | trivialPositiveIntValue(pos) and s = "-" + pos)
187187
}
188188

189-
private predicate intTrivial(Literal lit) {
190-
exists(string v | trivialIntValue(v) and v = lit.getLiteral())
189+
private predicate intTrivial(IntegerLiteral lit) {
190+
// Remove all `_` from literal, if any (e.g. `1_000_000`)
191+
exists(string v | trivialIntValue(v) and v = lit.getLiteral().replaceAll("_", ""))
191192
}
192193

193-
private predicate longTrivial(Literal lit) {
194-
exists(string v | trivialIntValue(v) and v + "L" = lit.getLiteral())
194+
private predicate longTrivial(LongLiteral lit) {
195+
exists(string v |
196+
trivialIntValue(v) and
197+
// Remove all `_` from literal, if any (e.g. `1_000_000L`)
198+
v + ["l", "L"] = lit.getLiteral().replaceAll("_", "")
199+
)
195200
}
196201

197202
private predicate powerOfTen(float f) {
198-
f = 10 or
199-
f = 100 or
200-
f = 1000 or
201-
f = 10000 or
202-
f = 100000 or
203-
f = 1000000 or
204-
f = 10000000 or
205-
f = 100000000 or
206-
f = 1000000000
203+
f = [10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000]
207204
}
208205

209206
private predicate floatTrivial(Literal lit) {
@@ -244,7 +241,7 @@ private predicate literalIsConstantInitializer(Literal literal, Field f) {
244241
}
245242

246243
private predicate nonTrivialValue(string value, Literal literal, string context) {
247-
value = literal.getLiteral() and
244+
value = literal.getValue() and
248245
not trivial(literal) and
249246
not literalIsConstantInitializer(literal, _) and
250247
not literal.getParent*() instanceof ArrayInit and
@@ -259,7 +256,7 @@ private predicate valueOccurrenceCount(string value, int n, string context) {
259256

260257
private predicate occurenceCount(Literal lit, string value, int n, string context) {
261258
valueOccurrenceCount(value, n, context) and
262-
value = lit.getLiteral() and
259+
value = lit.getValue() and
263260
nonTrivialValue(_, lit, context)
264261
}
265262

@@ -296,14 +293,7 @@ private predicate firstOccurrence(Literal lit, string value, string context, int
296293
)
297294
}
298295

299-
predicate isNumber(Literal lit) {
300-
lit.getType().getName() = "char" or
301-
lit.getType().getName() = "short" or
302-
lit.getType().getName() = "int" or
303-
lit.getType().getName() = "long" or
304-
lit.getType().getName() = "float" or
305-
lit.getType().getName() = "double"
306-
}
296+
predicate isNumber(Literal lit) { lit.getType() instanceof NumericOrCharType }
307297

308298
predicate magicConstant(Literal e, string msg) {
309299
exists(string value, int n, string context |
@@ -320,7 +310,7 @@ predicate magicConstant(Literal e, string msg) {
320310

321311
private predicate relevantField(Field f, string value) {
322312
exists(Literal lit |
323-
not trivial(lit) and value = lit.getLiteral() and literalIsConstantInitializer(lit, f)
313+
not trivial(lit) and value = lit.getValue() and literalIsConstantInitializer(lit, f)
324314
)
325315
}
326316

@@ -344,7 +334,7 @@ private predicate candidateConstantForLiteral(
344334
exists(Literal initLiteral |
345335
literalIsConstantInitializer(initLiteral, constField) and
346336
exists(string value |
347-
value = initLiteral.getLiteral() and
337+
value = initLiteral.getValue() and
348338
nonTrivialValue(value, magicLiteral, context) and
349339
fieldUsedInContext(constField, context)
350340
) and
@@ -401,7 +391,7 @@ predicate literalInsteadOfConstant(
401391
exists(string context |
402392
canUseFieldInsteadOfLiteral(constField, magicLiteral, context) and
403393
message =
404-
"Literal value '" + magicLiteral.getLiteral() + "' used " + " in a call to " + context +
394+
"Literal value '" + magicLiteral.getValue() + "' used " + " in a call to " + context +
405395
"; consider using the defined constant $@." and
406396
linkText = constField.getName() and
407397
(

java/ql/test/library-tests/Encryption/insecure.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ import default
22
import semmle.code.java.security.Encryption
33

44
from StringLiteral s
5-
where s.getLiteral().regexpMatch(getInsecureAlgorithmRegex())
5+
where s.getRepresentedString().regexpMatch(getInsecureAlgorithmRegex())
66
select s

java/ql/test/library-tests/Encryption/secure.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ import default
22
import semmle.code.java.security.Encryption
33

44
from StringLiteral s
5-
where s.getLiteral().regexpMatch(getSecureAlgorithmRegex())
5+
where s.getRepresentedString().regexpMatch(getSecureAlgorithmRegex())
66
select s

0 commit comments

Comments
 (0)