Skip to content

Commit 542d5a2

Browse files
authored
Merge pull request #14414 from owen-mc/go/fix-incorrect-integer-conversion-performance-regression
Go: Change MaxValueState API to get architecture bit size
2 parents 5c44f8b + fd9c1d3 commit 542d5a2

File tree

1 file changed

+22
-20
lines changed

1 file changed

+22
-20
lines changed

go/ql/lib/semmle/go/security/IncorrectIntegerConversionLib.qll

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,13 @@ private class MaxValueState extends TMaxValueState {
195195
*/
196196
int getBitSize() { this = TMkMaxValueState(result, _) }
197197

198-
/** Gets whether the architecture is 32 bit or 64 bit, or if it is unknown. */
199-
ArchitectureBitSize getArchitectureBitSize() { this = TMkMaxValueState(_, result) }
198+
private ArchitectureBitSize architectureBitSize() { this = TMkMaxValueState(_, result) }
199+
200+
/** Gets whether the architecture is 32 bit or 64 bit, if it is known. */
201+
int getArchitectureBitSize() { result = this.architectureBitSize().toInt() }
202+
203+
/** Holds if the architecture is not known. */
204+
predicate architectureBitSizeUnknown() { this.architectureBitSize().isUnknown() }
200205

201206
/**
202207
* Gets the bitsize we should use for a sink.
@@ -205,17 +210,16 @@ private class MaxValueState extends TMaxValueState {
205210
* we should use 32 bits, because that will find results that only exist on
206211
* 32-bit architectures.
207212
*/
208-
bindingset[default]
209-
int getSinkBitSize(int default) {
210-
if this = TMkMaxValueState(_, TMk64Bit()) then result = 64 else result = default
213+
int getSinkBitSize() {
214+
if this = TMkMaxValueState(_, TMk64Bit()) then result = 64 else result = 32
211215
}
212216

213217
/** Gets a textual representation of this element. */
214218
string toString() {
215219
exists(string suffix |
216-
suffix = " (on " + this.getArchitectureBitSize().toInt() + "-bit architecture)"
220+
suffix = " (on " + this.getArchitectureBitSize() + "-bit architecture)"
217221
or
218-
this.getArchitectureBitSize().isUnknown() and suffix = ""
222+
this.architectureBitSizeUnknown() and suffix = ""
219223
|
220224
result = "MaxValueState(max value <= 2^(" + this.getBitSize() + ")-1" + suffix
221225
)
@@ -336,9 +340,7 @@ class UpperBoundCheck extends BarrierFlowStateTransformer {
336340
}
337341

338342
override predicate barrierFor(MaxValueState flowstate) {
339-
// Use a default value of 32 for `MaxValueState.getSinkBitSize` because
340-
// this will find results that only exist on 32-bit architectures.
341-
g.isBoundFor(flowstate.getBitSize(), flowstate.getSinkBitSize(32))
343+
g.isBoundFor(flowstate.getBitSize(), flowstate.getSinkBitSize())
342344
}
343345

344346
override MaxValueState transform(MaxValueState state) {
@@ -347,11 +349,13 @@ class UpperBoundCheck extends BarrierFlowStateTransformer {
347349
max(int bitsize |
348350
bitsize = validBitSize() and
349351
bitsize < state.getBitSize() and
350-
// Use a default value of 32 for `MaxValueState.getSinkBitSize` because
351-
// this will find results that only exist on 32-bit architectures.
352-
not g.isBoundFor(bitsize, state.getSinkBitSize(32))
352+
not g.isBoundFor(bitsize, state.getSinkBitSize())
353353
) and
354-
result.getArchitectureBitSize() = state.getArchitectureBitSize()
354+
(
355+
result.getArchitectureBitSize() = state.getArchitectureBitSize()
356+
or
357+
state.architectureBitSizeUnknown() and result.architectureBitSizeUnknown()
358+
)
355359
}
356360
}
357361

@@ -395,10 +399,10 @@ private module ConversionWithoutBoundsCheckConfig implements DataFlow::StateConf
395399
then
396400
exists(int b | b = [32, 64] |
397401
state.getBitSize() = adjustBitSize(0, sourceIsSigned, b) and
398-
state.getArchitectureBitSize().toInt() = b
402+
state.getArchitectureBitSize() = b
399403
)
400404
else (
401-
state.getArchitectureBitSize().isUnknown() and
405+
state.architectureBitSizeUnknown() and
402406
state.getBitSize() =
403407
min(int bitsize |
404408
bitsize = validBitSize() and
@@ -419,10 +423,8 @@ private module ConversionWithoutBoundsCheckConfig implements DataFlow::StateConf
419423
additional predicate isSink2(DataFlow::TypeCastNode sink, FlowState state) {
420424
sink.asExpr() instanceof ConversionExpr and
421425
exists(int architectureBitSize, IntegerType integerType, int sinkBitsize, boolean sinkIsSigned |
422-
// Use a default value of 32 for `MaxValueState.getSinkBitSize` because
423-
// this will find results that only exist on 32-bit architectures.
424-
architectureBitSize = getIntTypeBitSize(sink.getFile(), state.getSinkBitSize(32)) and
425-
not (state.getArchitectureBitSize().toInt() = 32 and architectureBitSize = 64) and
426+
architectureBitSize = getIntTypeBitSize(sink.getFile(), state.getSinkBitSize()) and
427+
not (state.getArchitectureBitSize() = 32 and architectureBitSize = 64) and
426428
sink.getResultType().getUnderlyingType() = integerType and
427429
(
428430
sinkBitsize = integerType.getSize()

0 commit comments

Comments
 (0)