Skip to content

Commit 2747864

Browse files
committed
CPP: Bring the logic for argument indices together in getFormatArgumentIndexFor.
1 parent 7608840 commit 2747864

File tree

1 file changed

+48
-28
lines changed

1 file changed

+48
-28
lines changed

cpp/ql/src/semmle/code/cpp/commons/Printf.qll

Lines changed: 48 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -131,16 +131,11 @@ class FormattingFunctionCall extends Expr {
131131
}
132132

133133
/**
134-
* Gets the argument corresponding to the nth conversion specifier
134+
* Gets the argument corresponding to the nth conversion specifier.
135135
*/
136136
Expr getConversionArgument(int n) {
137-
exists(FormatLiteral fl, int b, int o |
138-
fl = this.getFormat() and
139-
b = sum(int i, int toSum | i < n and toSum = fl.getNumArgNeeded(i) | toSum) and
140-
o = fl.getNumArgNeeded(n) and
141-
o > 0 and
142-
result = this.getFormatArgument(b + o - 1)
143-
)
137+
result = this
138+
.getFormatArgument(this.getFormat().(FormatLiteral).getFormatArgumentIndexFor(n, 2))
144139
}
145140

146141
/**
@@ -149,12 +144,8 @@ class FormattingFunctionCall extends Expr {
149144
* an explicit minimum field width).
150145
*/
151146
Expr getMinFieldWidthArgument(int n) {
152-
exists(FormatLiteral fl, int b |
153-
fl = this.getFormat() and
154-
b = sum(int i, int toSum | i < n and toSum = fl.getNumArgNeeded(i) | toSum) and
155-
fl.hasImplicitMinFieldWidth(n) and
156-
result = this.getFormatArgument(b)
157-
)
147+
result = this
148+
.getFormatArgument(this.getFormat().(FormatLiteral).getFormatArgumentIndexFor(n, 0))
158149
}
159150

160151
/**
@@ -163,13 +154,8 @@ class FormattingFunctionCall extends Expr {
163154
* precision).
164155
*/
165156
Expr getPrecisionArgument(int n) {
166-
exists(FormatLiteral fl, int b, int o |
167-
fl = this.getFormat() and
168-
b = sum(int i, int toSum | i < n and toSum = fl.getNumArgNeeded(i) | toSum) and
169-
(if fl.hasImplicitMinFieldWidth(n) then o = 1 else o = 0) and
170-
fl.hasImplicitPrecision(n) and
171-
result = this.getFormatArgument(b + o)
172-
)
157+
result = this
158+
.getFormatArgument(this.getFormat().(FormatLiteral).getFormatArgumentIndexFor(n, 1))
173159
}
174160

175161
/**
@@ -784,19 +770,53 @@ class FormatLiteral extends Literal {
784770
)
785771
}
786772

773+
/**
774+
* Holds if the nth conversion specifier of this format string (if `mode = 2`), it's
775+
* minimum field width (if `mode = 0`) or it's precision (if `mode = 1`) requires a
776+
* format argument.
777+
*
778+
* Most conversion specifiers require a format argument, whereas minimum field width
779+
* and precision only require a format argument if they are present and a `*` was
780+
* used for it's value in the format string.
781+
*/
782+
private predicate hasFormatArgumentIndexFor(int n, int mode) {
783+
mode = 0 and
784+
this.hasImplicitMinFieldWidth(n)
785+
or
786+
mode = 1 and
787+
this.hasImplicitPrecision(n)
788+
or
789+
mode = 2 and
790+
exists(this.getConvSpecOffset(n)) and
791+
not this.getConversionChar(n) = "m"
792+
}
793+
794+
/**
795+
* Gets the format argument index for the nth conversion specifier of this format
796+
* string (if `mode = 2`), it's minimum field width (if `mode = 0`) or it's
797+
* precision (if `mode = 1`). Has no result if that element is not present. Does
798+
* not account for positional arguments (`$`).
799+
*/
800+
int getFormatArgumentIndexFor(int n, int mode) {
801+
hasFormatArgumentIndexFor(n, mode) and
802+
result = count(int n2, int mode2 |
803+
hasFormatArgumentIndexFor(n2, mode2) and
804+
(
805+
n2 < n
806+
or
807+
n2 = n and
808+
mode2 < mode
809+
)
810+
)
811+
}
812+
787813
/**
788814
* Gets the number of arguments required by the nth conversion specifier
789815
* of this format string.
790816
*/
791817
int getNumArgNeeded(int n) {
792818
exists(this.getConvSpecOffset(n)) and
793-
not this.getConversionChar(n) = "%" and
794-
exists(int n1, int n2, int n3 |
795-
(if this.hasImplicitMinFieldWidth(n) then n1 = 1 else n1 = 0) and
796-
(if this.hasImplicitPrecision(n) then n2 = 1 else n2 = 0) and
797-
(if this.getConversionChar(n) = "m" then n3 = 0 else n3 = 1) and
798-
result = n1 + n2 + n3
799-
)
819+
result = count(int mode | hasFormatArgumentIndexFor(n, mode))
800820
}
801821

802822
/**

0 commit comments

Comments
 (0)