Skip to content

Commit cacae95

Browse files
authored
Merge pull request github#12441 from smowton/smowton/fix/golang-incorrect-integer-conversion-sanitizer
Go: fix incorrect-integer-conversion sanitizer
2 parents ce937e7 + a63a4c2 commit cacae95

File tree

3 files changed

+34
-14
lines changed

3 files changed

+34
-14
lines changed

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,13 @@ class ConversionWithoutBoundsCheckConfig extends TaintTracking::Configuration {
123123
)
124124
}
125125

126-
override predicate isSink(DataFlow::Node sink) { this.isSinkWithBitSize(sink, sinkBitSize) }
126+
override predicate isSink(DataFlow::Node sink) {
127+
// We use the argument of the type conversion as the configuration sink so that we
128+
// can sanitize the result of the conversion to prevent flow on to further sinks
129+
// without needing to use `isSanitizerOut`, which doesn't work with flow states
130+
// (and therefore the legacy `TaintTracking::Configuration` class).
131+
this.isSinkWithBitSize(sink.getASuccessor(), sinkBitSize)
132+
}
127133

128134
override predicate isSanitizer(DataFlow::Node node) {
129135
// To catch flows that only happen on 32-bit architectures we
@@ -135,10 +141,9 @@ class ConversionWithoutBoundsCheckConfig extends TaintTracking::Configuration {
135141
g.isBoundFor(bitSize, sinkIsSigned)
136142
)
137143
or
138-
exists(DataFlow::Node sink, int bitSize |
144+
exists(int bitSize |
139145
isIncorrectIntegerConversion(sourceBitSize, bitSize) and
140-
this.isSinkWithBitSize(sink, bitSize) and
141-
TaintTracking::localTaintStep(sink, node)
146+
this.isSinkWithBitSize(node, bitSize)
142147
)
143148
}
144149
}

go/ql/src/Security/CWE-681/IncorrectIntegerConversionQuery.ql

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,13 @@ import semmle.go.security.IncorrectIntegerConversionLib
1919

2020
from
2121
DataFlow::PathNode source, DataFlow::PathNode sink, ConversionWithoutBoundsCheckConfig cfg,
22-
DataFlow::CallNode call
23-
where cfg.hasFlowPath(source, sink) and call.getResult(0) = source.getNode()
24-
select sink.getNode(), source, sink,
22+
DataFlow::CallNode call, DataFlow::Node sinkConverted
23+
where
24+
cfg.hasFlowPath(source, sink) and
25+
call.getResult(0) = source.getNode() and
26+
sinkConverted = sink.getNode().getASuccessor()
27+
select sinkConverted, source, sink,
2528
"Incorrect conversion of " +
2629
describeBitSize(cfg.getSourceBitSize(), getIntTypeBitSize(source.getNode().getFile())) +
27-
" from $@ to a lower bit size type " + sink.getNode().getType().getUnderlyingType().getName() +
30+
" from $@ to a lower bit size type " + sinkConverted.getType().getUnderlyingType().getName() +
2831
" without an upper bound check.", source, call.getTarget().getQualifiedName()
Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,23 @@
11
import go
2-
import TestUtilities.InlineFlowTest
2+
import TestUtilities.InlineExpectationsTest
33
import semmle.go.security.IncorrectIntegerConversionLib
44

5-
class IncorrectIntegerConversionTest extends InlineFlowTest {
6-
override DataFlow::Configuration getValueFlowConfig() {
7-
result = any(ConversionWithoutBoundsCheckConfig config)
8-
}
5+
class TestIncorrectIntegerConversion extends InlineExpectationsTest {
6+
TestIncorrectIntegerConversion() { this = "TestIncorrectIntegerConversion" }
7+
8+
override string getARelevantTag() { result = "hasValueFlow" }
99

10-
override DataFlow::Configuration getTaintFlowConfig() { none() }
10+
override predicate hasActualResult(Location location, string element, string tag, string value) {
11+
tag = "hasValueFlow" and
12+
exists(DataFlow::Node sink, DataFlow::Node sinkConverted |
13+
any(ConversionWithoutBoundsCheckConfig config).hasFlowTo(sink) and
14+
sinkConverted = sink.getASuccessor()
15+
|
16+
sinkConverted
17+
.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(),
18+
location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and
19+
element = sinkConverted.toString() and
20+
value = "\"" + sinkConverted.toString() + "\""
21+
)
22+
}
1123
}

0 commit comments

Comments
 (0)