Skip to content

Commit 655aa70

Browse files
authored
Merge pull request github#12247 from smowton/smowton/fix/integer-conversion-sign
Go integer conversion: check against sink, not source signedness
2 parents f72cb5f + c7da1c9 commit 655aa70

File tree

3 files changed

+18
-13
lines changed

3 files changed

+18
-13
lines changed

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

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,14 @@ private predicate isIncorrectIntegerConversion(int sourceBitSize, int sinkBitSiz
5656
* integer types, which could cause unexpected values.
5757
*/
5858
class ConversionWithoutBoundsCheckConfig extends TaintTracking::Configuration {
59-
boolean sourceIsSigned;
59+
boolean sinkIsSigned;
6060
int sourceBitSize;
6161
int sinkBitSize;
6262

6363
ConversionWithoutBoundsCheckConfig() {
64-
sourceIsSigned in [true, false] and
64+
sinkIsSigned in [true, false] and
6565
isIncorrectIntegerConversion(sourceBitSize, sinkBitSize) and
66-
this = "ConversionWithoutBoundsCheckConfig" + sourceBitSize + sourceIsSigned + sinkBitSize
66+
this = "ConversionWithoutBoundsCheckConfig" + sourceBitSize + sinkIsSigned + sinkBitSize
6767
}
6868

6969
/** Gets the bit size of the source. */
@@ -75,11 +75,6 @@ class ConversionWithoutBoundsCheckConfig extends TaintTracking::Configuration {
7575
|
7676
c.getTarget() = ip and source = c.getResult(0)
7777
|
78-
(
79-
if ip.getResultType(0) instanceof SignedIntegerType
80-
then sourceIsSigned = true
81-
else sourceIsSigned = false
82-
) and
8378
(
8479
apparentBitSize = ip.getTargetBitSize()
8580
or
@@ -112,10 +107,13 @@ class ConversionWithoutBoundsCheckConfig extends TaintTracking::Configuration {
112107
predicate isSinkWithBitSize(DataFlow::TypeCastNode sink, int bitSize) {
113108
sink.asExpr() instanceof ConversionExpr and
114109
exists(IntegerType integerType | sink.getResultType().getUnderlyingType() = integerType |
115-
bitSize = integerType.getSize()
116-
or
117-
not exists(integerType.getSize()) and
118-
bitSize = getIntTypeBitSize(sink.getFile())
110+
(
111+
bitSize = integerType.getSize()
112+
or
113+
not exists(integerType.getSize()) and
114+
bitSize = getIntTypeBitSize(sink.getFile())
115+
) and
116+
if integerType instanceof SignedIntegerType then sinkIsSigned = true else sinkIsSigned = false
119117
) and
120118
not exists(ShrExpr shrExpr |
121119
shrExpr.getLeftOperand().getGlobalValueNumber() =
@@ -134,7 +132,7 @@ class ConversionWithoutBoundsCheckConfig extends TaintTracking::Configuration {
134132
if sinkBitSize != 0 then bitSize = sinkBitSize else bitSize = 32
135133
|
136134
node = DataFlow::BarrierGuard<upperBoundCheckGuard/3>::getABarrierNodeForGuard(g) and
137-
g.isBoundFor(bitSize, sourceIsSigned)
135+
g.isBoundFor(bitSize, sinkIsSigned)
138136
)
139137
}
140138

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* The query `go/incorrect-integer-conversion` now correctly recognises guards of the form `if val <= x` to protect a conversion `uintX(val)` when `x` is in the range `(math.MaxIntX, math.MaxUintX]`.

go/ql/test/query-tests/Security/CWE-681/IncorrectIntegerConversion.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,9 @@ func testBoundsChecking(input string) {
264264
_ = int16(parsed)
265265
}
266266
}
267+
if parsed <= math.MaxUint16 {
268+
_ = uint16(parsed)
269+
}
267270
}
268271
{
269272
parsed, err := strconv.ParseUint(input, 10, 32)

0 commit comments

Comments
 (0)