Fix getAnArgUsageOffset and improve its space complexity

Also add tests checking the output of the new function
This commit is contained in:
Chris Smowton
2021-05-12 12:15:25 +01:00
parent 0db5484399
commit f388aae78e
4 changed files with 61 additions and 6 deletions

View File

@@ -175,14 +175,17 @@ class FormattingCall extends Call {
)
}
/** Gets the `i`th argument to be formatted. */
/** Gets the `i`th argument to be formatted. The index `i` is one-based. */
Expr getArgumentToBeFormatted(int i) {
i >= 0 and
i >= 1 and
if this.hasExplicitVarargsArray()
then
result =
this.getArgument(1 + this.getFormatStringIndex()).(ArrayCreationExpr).getInit().getInit(i)
else result = this.getArgument(this.getFormatStringIndex() + 1 + i)
this.getArgument(1 + this.getFormatStringIndex())
.(ArrayCreationExpr)
.getInit()
.getInit(i - 1)
else result = this.getArgument(this.getFormatStringIndex() + i)
}
/** Holds if the varargs argument is given as an explicit array. */
@@ -441,14 +444,21 @@ private class PrintfFormatString extends FormatString {
not result = fmtSpecRefersToSpecificIndex(_)
}
private int getFmtSpecRank(int specOffset) {
rank[result](int i | this.fmtSpecIsRef(i)) = specOffset
}
override int getAnArgUsageOffset(int argNo) {
argNo = fmtSpecRefersToSpecificIndex(result)
or
fmtSpecRefersToSequentialIndex(result) and
argNo = count(int i | i < result and fmtSpecRefersToSequentialIndex(i))
result = rank[argNo](int i | fmtSpecRefersToSequentialIndex(i))
or
fmtSpecRefersToPrevious(result) and
argNo = count(int i | i < result and fmtSpecRefersToSequentialIndex(i)) - 1
exists(int previousOffset |
getFmtSpecRank(previousOffset) = getFmtSpecRank(result) - 1 and
previousOffset = getAnArgUsageOffset(argNo)
)
}
}

View File

@@ -0,0 +1,17 @@
public class Test {
public static void test () {
String.format("%s", "", "");
String.format("s", "");
String.format("%2$s %2$s", "", "");
String.format("%2$s %1$s", "", "");
String.format("%2$s %s", "");
String.format("%s%<s", "", "");
String.format("%s%%%%%%%%s%n", "", "");
String.format("%s%%%%%%%%s%n", "");
String.format("%s%%%%%%%s%n", "", "");
String.format("%s%%%%%%%s%n", "");
String.format("%2$s %% %n %1$s %<s %s %<s %<s %s %<s %1$s %<s", "", "");
}
}

View File

@@ -0,0 +1,22 @@
| %2$s %1$s | 1 | 5 |
| %2$s %1$s | 2 | 0 |
| %2$s %2$s | 2 | 0 |
| %2$s %2$s | 2 | 5 |
| %2$s %% %n %1$s %<s %s %<s %<s %s %<s %1$s %<s | 1 | 11 |
| %2$s %% %n %1$s %<s %s %<s %<s %s %<s %1$s %<s | 1 | 16 |
| %2$s %% %n %1$s %<s %s %<s %<s %s %<s %1$s %<s | 1 | 20 |
| %2$s %% %n %1$s %<s %s %<s %<s %s %<s %1$s %<s | 1 | 23 |
| %2$s %% %n %1$s %<s %s %<s %<s %s %<s %1$s %<s | 1 | 27 |
| %2$s %% %n %1$s %<s %s %<s %<s %s %<s %1$s %<s | 1 | 38 |
| %2$s %% %n %1$s %<s %s %<s %<s %s %<s %1$s %<s | 1 | 43 |
| %2$s %% %n %1$s %<s %s %<s %<s %s %<s %1$s %<s | 2 | 0 |
| %2$s %% %n %1$s %<s %s %<s %<s %s %<s %1$s %<s | 2 | 31 |
| %2$s %% %n %1$s %<s %s %<s %<s %s %<s %1$s %<s | 2 | 34 |
| %2$s %s | 1 | 5 |
| %2$s %s | 2 | 0 |
| %s | 1 | 0 |
| %s%%%%%%%%s%n | 1 | 0 |
| %s%%%%%%%s%n | 1 | 0 |
| %s%%%%%%%s%n | 2 | 8 |
| %s%<s | 1 | 0 |
| %s%<s | 1 | 2 |

View File

@@ -0,0 +1,6 @@
import java
import semmle.code.java.StringFormat
from FormatString f, int argNo, int offset
where offset = f.getAnArgUsageOffset(argNo)
select f, argNo, offset