Skip to content

Commit f388aae

Browse files
committed
Fix getAnArgUsageOffset and improve its space complexity
Also add tests checking the output of the new function
1 parent 0db5484 commit f388aae

File tree

4 files changed

+61
-6
lines changed

4 files changed

+61
-6
lines changed

java/ql/src/semmle/code/java/StringFormat.qll

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -175,14 +175,17 @@ class FormattingCall extends Call {
175175
)
176176
}
177177

178-
/** Gets the `i`th argument to be formatted. */
178+
/** Gets the `i`th argument to be formatted. The index `i` is one-based. */
179179
Expr getArgumentToBeFormatted(int i) {
180-
i >= 0 and
180+
i >= 1 and
181181
if this.hasExplicitVarargsArray()
182182
then
183183
result =
184-
this.getArgument(1 + this.getFormatStringIndex()).(ArrayCreationExpr).getInit().getInit(i)
185-
else result = this.getArgument(this.getFormatStringIndex() + 1 + i)
184+
this.getArgument(1 + this.getFormatStringIndex())
185+
.(ArrayCreationExpr)
186+
.getInit()
187+
.getInit(i - 1)
188+
else result = this.getArgument(this.getFormatStringIndex() + i)
186189
}
187190

188191
/** Holds if the varargs argument is given as an explicit array. */
@@ -441,14 +444,21 @@ private class PrintfFormatString extends FormatString {
441444
not result = fmtSpecRefersToSpecificIndex(_)
442445
}
443446

447+
private int getFmtSpecRank(int specOffset) {
448+
rank[result](int i | this.fmtSpecIsRef(i)) = specOffset
449+
}
450+
444451
override int getAnArgUsageOffset(int argNo) {
445452
argNo = fmtSpecRefersToSpecificIndex(result)
446453
or
447454
fmtSpecRefersToSequentialIndex(result) and
448-
argNo = count(int i | i < result and fmtSpecRefersToSequentialIndex(i))
455+
result = rank[argNo](int i | fmtSpecRefersToSequentialIndex(i))
449456
or
450457
fmtSpecRefersToPrevious(result) and
451-
argNo = count(int i | i < result and fmtSpecRefersToSequentialIndex(i)) - 1
458+
exists(int previousOffset |
459+
getFmtSpecRank(previousOffset) = getFmtSpecRank(result) - 1 and
460+
previousOffset = getAnArgUsageOffset(argNo)
461+
)
452462
}
453463
}
454464

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
public class Test {
2+
3+
public static void test () {
4+
String.format("%s", "", "");
5+
String.format("s", "");
6+
String.format("%2$s %2$s", "", "");
7+
String.format("%2$s %1$s", "", "");
8+
String.format("%2$s %s", "");
9+
String.format("%s%<s", "", "");
10+
String.format("%s%%%%%%%%s%n", "", "");
11+
String.format("%s%%%%%%%%s%n", "");
12+
String.format("%s%%%%%%%s%n", "", "");
13+
String.format("%s%%%%%%%s%n", "");
14+
String.format("%2$s %% %n %1$s %<s %s %<s %<s %s %<s %1$s %<s", "", "");
15+
}
16+
17+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
| %2$s %1$s | 1 | 5 |
2+
| %2$s %1$s | 2 | 0 |
3+
| %2$s %2$s | 2 | 0 |
4+
| %2$s %2$s | 2 | 5 |
5+
| %2$s %% %n %1$s %<s %s %<s %<s %s %<s %1$s %<s | 1 | 11 |
6+
| %2$s %% %n %1$s %<s %s %<s %<s %s %<s %1$s %<s | 1 | 16 |
7+
| %2$s %% %n %1$s %<s %s %<s %<s %s %<s %1$s %<s | 1 | 20 |
8+
| %2$s %% %n %1$s %<s %s %<s %<s %s %<s %1$s %<s | 1 | 23 |
9+
| %2$s %% %n %1$s %<s %s %<s %<s %s %<s %1$s %<s | 1 | 27 |
10+
| %2$s %% %n %1$s %<s %s %<s %<s %s %<s %1$s %<s | 1 | 38 |
11+
| %2$s %% %n %1$s %<s %s %<s %<s %s %<s %1$s %<s | 1 | 43 |
12+
| %2$s %% %n %1$s %<s %s %<s %<s %s %<s %1$s %<s | 2 | 0 |
13+
| %2$s %% %n %1$s %<s %s %<s %<s %s %<s %1$s %<s | 2 | 31 |
14+
| %2$s %% %n %1$s %<s %s %<s %<s %s %<s %1$s %<s | 2 | 34 |
15+
| %2$s %s | 1 | 5 |
16+
| %2$s %s | 2 | 0 |
17+
| %s | 1 | 0 |
18+
| %s%%%%%%%%s%n | 1 | 0 |
19+
| %s%%%%%%%s%n | 1 | 0 |
20+
| %s%%%%%%%s%n | 2 | 8 |
21+
| %s%<s | 1 | 0 |
22+
| %s%<s | 1 | 2 |
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import java
2+
import semmle.code.java.StringFormat
3+
4+
from FormatString f, int argNo, int offset
5+
where offset = f.getAnArgUsageOffset(argNo)
6+
select f, argNo, offset

0 commit comments

Comments
 (0)