@@ -53,132 +53,6 @@ int getIntTypeBitSize(File file, int architectureSpecificBitSize) {
5353 result = architectureSpecificBitSize
5454}
5555
56- /**
57- * Holds if converting from an integer types with size `sourceBitSize` to
58- * one with size `sinkBitSize` can produce unexpected values, where 0 means
59- * architecture-dependent.
60- *
61- * Architecture-dependent bit sizes can be 32 or 64. To catch flows that
62- * only manifest on 64-bit architectures we consider an
63- * architecture-dependent source bit size to be 64. To catch flows that
64- * only happen on 32-bit architectures we consider an
65- * architecture-dependent sink bit size to be 32. We exclude the case where
66- * both source and sink have architecture-dependent bit sizes.
67- */
68- private predicate isIncorrectIntegerConversion ( int sourceBitSize , int sinkBitSize ) {
69- sourceBitSize in [ 16 , 32 , 64 ] and
70- sinkBitSize in [ 8 , 16 , 32 ] and
71- sourceBitSize > sinkBitSize
72- or
73- // Treat `sourceBitSize = 0` like `sourceBitSize = 64`, and exclude `sinkBitSize = 0`
74- sourceBitSize = 0 and
75- sinkBitSize in [ 8 , 16 , 32 ]
76- or
77- // Treat `sinkBitSize = 0` like `sinkBitSize = 32`, and exclude `sourceBitSize = 0`
78- sourceBitSize = 64 and
79- sinkBitSize = 0
80- }
81-
82- /**
83- * DEPRECATED: use `Flow` instead.
84- *
85- * A taint-tracking configuration for reasoning about when an integer
86- * obtained from parsing a string flows to a type conversion to a smaller
87- * integer types, which could cause unexpected values.
88- */
89- deprecated class ConversionWithoutBoundsCheckConfig extends TaintTracking:: Configuration {
90- boolean sinkIsSigned ;
91- int sourceBitSize ;
92- int sinkBitSize ;
93-
94- ConversionWithoutBoundsCheckConfig ( ) {
95- sinkIsSigned in [ true , false ] and
96- isIncorrectIntegerConversion ( sourceBitSize , sinkBitSize ) and
97- this = "ConversionWithoutBoundsCheckConfig" + sourceBitSize + sinkIsSigned + sinkBitSize
98- }
99-
100- /** Gets the bit size of the source. */
101- int getSourceBitSize ( ) { result = sourceBitSize }
102-
103- override predicate isSource ( DataFlow:: Node source ) {
104- exists (
105- DataFlow:: CallNode c , IntegerParser:: Range ip , int apparentBitSize , int effectiveBitSize
106- |
107- c .getTarget ( ) = ip and source = c .getResult ( 0 )
108- |
109- (
110- apparentBitSize = ip .getTargetBitSize ( )
111- or
112- // If we are reading a variable, check if it is
113- // `strconv.IntSize`, and use 0 if it is.
114- exists ( DataFlow:: Node rawBitSize | rawBitSize = ip .getTargetBitSizeInput ( ) .getNode ( c ) |
115- if rawBitSize = any ( Strconv:: IntSize intSize ) .getARead ( )
116- then apparentBitSize = 0
117- else apparentBitSize = rawBitSize .getIntValue ( )
118- )
119- ) and
120- (
121- if apparentBitSize = 0
122- then effectiveBitSize = getIntTypeBitSize ( source .getFile ( ) , 0 )
123- else effectiveBitSize = apparentBitSize
124- ) and
125- // `effectiveBitSize` could be any value between 0 and 64, but we
126- // can round it up to the nearest size of an integer type without
127- // changing behavior.
128- sourceBitSize = min ( int b | b in [ 0 , 8 , 16 , 32 , 64 ] and b >= effectiveBitSize )
129- )
130- }
131-
132- /**
133- * Holds if `sink` is a typecast to an integer type with size `bitSize` (where
134- * 0 represents architecture-dependent) and the expression being typecast is
135- * not also in a right-shift expression. We allow this case because it is
136- * a common pattern to serialise `byte(v)`, `byte(v >> 8)`, and so on.
137- */
138- predicate isSinkWithBitSize ( DataFlow:: TypeCastNode sink , int bitSize ) {
139- sink .asExpr ( ) instanceof ConversionExpr and
140- exists ( IntegerType integerType | sink .getResultType ( ) .getUnderlyingType ( ) = integerType |
141- (
142- bitSize = integerType .getSize ( )
143- or
144- not exists ( integerType .getSize ( ) ) and
145- bitSize = getIntTypeBitSize ( sink .getFile ( ) , 0 )
146- ) and
147- if integerType instanceof SignedIntegerType then sinkIsSigned = true else sinkIsSigned = false
148- ) and
149- not exists ( ShrExpr shrExpr |
150- shrExpr .getLeftOperand ( ) .getGlobalValueNumber ( ) =
151- sink .getOperand ( ) .asExpr ( ) .getGlobalValueNumber ( ) or
152- shrExpr .getLeftOperand ( ) .( AndExpr ) .getAnOperand ( ) .getGlobalValueNumber ( ) =
153- sink .getOperand ( ) .asExpr ( ) .getGlobalValueNumber ( )
154- )
155- }
156-
157- override predicate isSink ( DataFlow:: Node sink ) {
158- // We use the argument of the type conversion as the configuration sink so that we
159- // can sanitize the result of the conversion to prevent flow on to further sinks
160- // without needing to use `isSanitizerOut`, which doesn't work with flow states
161- // (and therefore the legacy `TaintTracking::Configuration` class).
162- this .isSinkWithBitSize ( sink .getASuccessor ( ) , sinkBitSize )
163- }
164-
165- override predicate isSanitizer ( DataFlow:: Node node ) {
166- // To catch flows that only happen on 32-bit architectures we
167- // consider an architecture-dependent sink bit size to be 32.
168- exists ( UpperBoundCheckGuard g , int bitSize |
169- if sinkBitSize != 0 then bitSize = sinkBitSize else bitSize = 32
170- |
171- node = DataFlow:: BarrierGuard< upperBoundCheckGuard / 3 > :: getABarrierNodeForGuard ( g ) and
172- if sinkIsSigned = true then g .isBoundFor ( bitSize , 32 ) else g .isBoundFor ( bitSize - 1 , 32 )
173- )
174- or
175- exists ( int bitSize |
176- isIncorrectIntegerConversion ( sourceBitSize , bitSize ) and
177- this .isSinkWithBitSize ( node , bitSize )
178- )
179- }
180- }
181-
18256private int validBitSize ( ) { result = [ 7 , 8 , 15 , 16 , 31 , 32 , 63 , 64 ] }
18357
18458private newtype TArchitectureBitSize =
0 commit comments