@@ -20,17 +20,22 @@ class BufferWriteEstimationReason extends TBufferWriteEstimationReason {
20
20
}
21
21
22
22
string toString ( ) {
23
- this = TTypeBoundsAnalysis ( ) and result = "based on type bounds" or
23
+ this = TTypeBoundsAnalysis ( ) and result = "based on type bounds"
24
+ or
24
25
this = TValueFlowAnalysis ( ) and result = "based on flow analysis of value bounds"
25
26
}
26
27
27
28
BufferWriteEstimationReason combineWith ( BufferWriteEstimationReason other ) {
28
- ( this = TTypeBoundsAnalysis ( ) or other = TTypeBoundsAnalysis ( ) ) and result = TTypeBoundsAnalysis ( ) or
29
- ( this = TValueFlowAnalysis ( ) and other = TValueFlowAnalysis ( ) ) and result = TValueFlowAnalysis ( )
29
+ ( this = TTypeBoundsAnalysis ( ) or other = TTypeBoundsAnalysis ( ) ) and
30
+ result = TTypeBoundsAnalysis ( )
31
+ or
32
+ ( this = TValueFlowAnalysis ( ) and other = TValueFlowAnalysis ( ) ) and
33
+ result = TValueFlowAnalysis ( )
30
34
}
31
35
}
32
36
33
37
BufferWriteEstimationReason typeBoundsAnalysis ( ) { result = TTypeBoundsAnalysis ( ) }
38
+
34
39
BufferWriteEstimationReason valueFlowAnalysis ( ) { result = TValueFlowAnalysis ( ) }
35
40
36
41
class PrintfFormatAttribute extends FormatAttribute {
@@ -1014,6 +1019,8 @@ class FormatLiteral extends Literal {
1014
1019
* conversion specifier of this format string; has no result if this cannot
1015
1020
* be determined.
1016
1021
*/
1022
+ int getMaxConvertedLength ( int n ) { result = max ( int l | l = getMaxConvertedLength ( n , _) | l ) }
1023
+
1017
1024
int getMaxConvertedLength ( int n , BufferWriteEstimationReason reason ) {
1018
1025
exists ( int len |
1019
1026
(
@@ -1026,10 +1033,12 @@ class FormatLiteral extends Literal {
1026
1033
) and
1027
1034
(
1028
1035
this .getConversionChar ( n ) = "%" and
1029
- len = 1 and reason = TValueFlowAnalysis ( )
1036
+ len = 1 and
1037
+ reason = TValueFlowAnalysis ( )
1030
1038
or
1031
1039
this .getConversionChar ( n ) .toLowerCase ( ) = "c" and
1032
- len = 1 and reason = TValueFlowAnalysis ( ) // e.g. 'a'
1040
+ len = 1 and
1041
+ reason = TValueFlowAnalysis ( ) // e.g. 'a'
1033
1042
or
1034
1043
this .getConversionChar ( n ) .toLowerCase ( ) = "f" and
1035
1044
exists ( int dot , int afterdot |
@@ -1043,7 +1052,8 @@ class FormatLiteral extends Literal {
1043
1052
afterdot = 6
1044
1053
) and
1045
1054
len = 1 + 309 + dot + afterdot
1046
- ) and reason = TTypeBoundsAnalysis ( ) // e.g. -1e308="-100000"...
1055
+ ) and
1056
+ reason = TTypeBoundsAnalysis ( ) // e.g. -1e308="-100000"...
1047
1057
or
1048
1058
this .getConversionChar ( n ) .toLowerCase ( ) = "e" and
1049
1059
exists ( int dot , int afterdot |
@@ -1057,7 +1067,8 @@ class FormatLiteral extends Literal {
1057
1067
afterdot = 6
1058
1068
) and
1059
1069
len = 1 + 1 + dot + afterdot + 1 + 1 + 3
1060
- ) and reason = TTypeBoundsAnalysis ( ) // -1e308="-1.000000e+308"
1070
+ ) and
1071
+ reason = TTypeBoundsAnalysis ( ) // -1e308="-1.000000e+308"
1061
1072
or
1062
1073
this .getConversionChar ( n ) .toLowerCase ( ) = "g" and
1063
1074
exists ( int dot , int afterdot |
@@ -1080,77 +1091,79 @@ class FormatLiteral extends Literal {
1080
1091
// (e.g. 123456, 0.000123456 are just OK)
1081
1092
// so case %f can be at most P characters + 4 zeroes, sign, dot = P + 6
1082
1093
len = ( afterdot .maximum ( 1 ) + 6 ) .maximum ( 1 + 1 + dot + afterdot + 1 + 1 + 3 )
1083
- ) and reason = TTypeBoundsAnalysis ( ) // (e.g. "-1.59203e-319")
1094
+ ) and
1095
+ reason = TTypeBoundsAnalysis ( ) // (e.g. "-1.59203e-319")
1084
1096
or
1085
1097
this .getConversionChar ( n ) .toLowerCase ( ) = [ "d" , "i" ] and
1086
1098
// e.g. -2^31 = "-2147483648"
1087
1099
exists ( float typeBasedBound , float valueBasedBound |
1088
- // The first case handles length sub-specifiers
1089
- // Subtract one in the exponent because one bit is for the sign.
1090
- // Add 1 to account for the possible sign in the output.
1091
- typeBasedBound = 1 + lengthInBase10 ( 2 .pow ( this .getIntegralDisplayType ( n ) .getSize ( ) * 8 - 1 ) ) and
1092
- // The second case uses range analysis to deduce a length that's shorter than the length
1093
- // of the number -2^31.
1094
- exists ( Expr arg , float lower , float upper , float typeLower , float typeUpper |
1095
- arg = this .getUse ( ) .getConversionArgument ( n ) and
1096
- lower = lowerBound ( arg .getFullyConverted ( ) ) and
1097
- upper = upperBound ( arg .getFullyConverted ( ) ) and
1098
- typeLower = exprMinVal ( arg .getFullyConverted ( ) ) and
1099
- typeUpper = exprMaxVal ( arg .getFullyConverted ( ) )
1100
- |
1101
- valueBasedBound =
1102
- max ( int cand |
1103
- // Include the sign bit in the length if it can be negative
1104
- (
1105
- if lower < 0
1106
- then cand = 1 + lengthInBase10 ( lower .abs ( ) )
1107
- else cand = lengthInBase10 ( lower )
1108
- )
1109
- or
1110
- (
1111
- if upper < 0
1112
- then cand = 1 + lengthInBase10 ( upper .abs ( ) )
1113
- else cand = lengthInBase10 ( upper )
1114
- )
1115
- ) and
1116
- (
1117
- if lower > typeLower or upper < typeUpper
1118
- then reason = TValueFlowAnalysis ( )
1119
- else reason = TTypeBoundsAnalysis ( )
1120
- )
1121
- ) and
1122
- len = valueBasedBound .minimum ( typeBasedBound )
1100
+ // The first case handles length sub-specifiers
1101
+ // Subtract one in the exponent because one bit is for the sign.
1102
+ // Add 1 to account for the possible sign in the output.
1103
+ typeBasedBound =
1104
+ 1 + lengthInBase10 ( 2 .pow ( this .getIntegralDisplayType ( n ) .getSize ( ) * 8 - 1 ) ) and
1105
+ // The second case uses range analysis to deduce a length that's shorter than the length
1106
+ // of the number -2^31.
1107
+ exists ( Expr arg , float lower , float upper , float typeLower , float typeUpper |
1108
+ arg = this .getUse ( ) .getConversionArgument ( n ) and
1109
+ lower = lowerBound ( arg .getFullyConverted ( ) ) and
1110
+ upper = upperBound ( arg .getFullyConverted ( ) ) and
1111
+ typeLower = exprMinVal ( arg .getFullyConverted ( ) ) and
1112
+ typeUpper = exprMaxVal ( arg .getFullyConverted ( ) )
1113
+ |
1114
+ valueBasedBound =
1115
+ max ( int cand |
1116
+ // Include the sign bit in the length if it can be negative
1117
+ (
1118
+ if lower < 0
1119
+ then cand = 1 + lengthInBase10 ( lower .abs ( ) )
1120
+ else cand = lengthInBase10 ( lower )
1121
+ )
1122
+ or
1123
+ (
1124
+ if upper < 0
1125
+ then cand = 1 + lengthInBase10 ( upper .abs ( ) )
1126
+ else cand = lengthInBase10 ( upper )
1127
+ )
1128
+ ) and
1129
+ (
1130
+ if lower > typeLower or upper < typeUpper
1131
+ then reason = TValueFlowAnalysis ( )
1132
+ else reason = TTypeBoundsAnalysis ( )
1133
+ )
1134
+ ) and
1135
+ len = valueBasedBound .minimum ( typeBasedBound )
1123
1136
)
1124
1137
or
1125
1138
this .getConversionChar ( n ) .toLowerCase ( ) = "u" and
1126
1139
// e.g. 2^32 - 1 = "4294967295"
1127
1140
exists ( float typeBasedBound , float valueBasedBound |
1128
- // The first case handles length sub-specifiers
1129
- typeBasedBound = lengthInBase10 ( 2 .pow ( this .getIntegralDisplayType ( n ) .getSize ( ) * 8 ) - 1 ) and
1130
- // The second case uses range analysis to deduce a length that's shorter than
1131
- // the length of the number 2^31 - 1.
1132
- exists ( Expr arg , float lower , float upper , float typeLower , float typeUpper |
1133
- arg = this .getUse ( ) .getConversionArgument ( n ) and
1134
- lower = lowerBound ( arg .getFullyConverted ( ) ) and
1135
- upper = upperBound ( arg .getFullyConverted ( ) ) and
1136
- typeLower = exprMinVal ( arg .getFullyConverted ( ) ) and
1137
- typeUpper = exprMaxVal ( arg .getFullyConverted ( ) )
1138
- |
1139
- valueBasedBound =
1140
- lengthInBase10 ( max ( float cand |
1141
+ // The first case handles length sub-specifiers
1142
+ typeBasedBound = lengthInBase10 ( 2 .pow ( this .getIntegralDisplayType ( n ) .getSize ( ) * 8 ) - 1 ) and
1143
+ // The second case uses range analysis to deduce a length that's shorter than
1144
+ // the length of the number 2^31 - 1.
1145
+ exists ( Expr arg , float lower , float upper , float typeLower , float typeUpper |
1146
+ arg = this .getUse ( ) .getConversionArgument ( n ) and
1147
+ lower = lowerBound ( arg .getFullyConverted ( ) ) and
1148
+ upper = upperBound ( arg .getFullyConverted ( ) ) and
1149
+ typeLower = exprMinVal ( arg .getFullyConverted ( ) ) and
1150
+ typeUpper = exprMaxVal ( arg .getFullyConverted ( ) )
1151
+ |
1152
+ valueBasedBound =
1153
+ lengthInBase10 ( max ( float cand |
1141
1154
// If lower can be negative we use `(unsigned)-1` as the candidate value.
1142
1155
lower < 0 and
1143
1156
cand = 2 .pow ( any ( IntType t | t .isUnsigned ( ) ) .getSize ( ) * 8 )
1144
1157
or
1145
1158
cand = upper
1146
1159
) ) and
1147
- (
1148
- if lower > typeLower or upper < typeUpper
1149
- then reason = TValueFlowAnalysis ( )
1150
- else reason = TTypeBoundsAnalysis ( )
1151
- )
1152
- ) and
1153
- len = valueBasedBound .minimum ( typeBasedBound )
1160
+ (
1161
+ if lower > typeLower or upper < typeUpper
1162
+ then reason = TValueFlowAnalysis ( )
1163
+ else reason = TTypeBoundsAnalysis ( )
1164
+ )
1165
+ ) and
1166
+ len = valueBasedBound .minimum ( typeBasedBound )
1154
1167
)
1155
1168
or
1156
1169
this .getConversionChar ( n ) .toLowerCase ( ) = "x" and
@@ -1170,7 +1183,8 @@ class FormatLiteral extends Literal {
1170
1183
(
1171
1184
if this .hasAlternateFlag ( n ) then len = 2 + baseLen else len = baseLen // "0x"
1172
1185
)
1173
- ) and reason = TTypeBoundsAnalysis ( )
1186
+ ) and
1187
+ reason = TTypeBoundsAnalysis ( )
1174
1188
or
1175
1189
this .getConversionChar ( n ) .toLowerCase ( ) = "p" and
1176
1190
exists ( PointerType ptrType , int baseLen |
@@ -1179,7 +1193,8 @@ class FormatLiteral extends Literal {
1179
1193
(
1180
1194
if this .hasAlternateFlag ( n ) then len = 2 + baseLen else len = baseLen // "0x"
1181
1195
)
1182
- ) and reason = TValueFlowAnalysis ( )
1196
+ ) and
1197
+ reason = TValueFlowAnalysis ( )
1183
1198
or
1184
1199
this .getConversionChar ( n ) .toLowerCase ( ) = "o" and
1185
1200
// e.g. 2^32 - 1 = "37777777777"
@@ -1198,7 +1213,8 @@ class FormatLiteral extends Literal {
1198
1213
(
1199
1214
if this .hasAlternateFlag ( n ) then len = 1 + baseLen else len = baseLen // "0"
1200
1215
)
1201
- ) and reason = TTypeBoundsAnalysis ( )
1216
+ ) and
1217
+ reason = TTypeBoundsAnalysis ( )
1202
1218
or
1203
1219
this .getConversionChar ( n ) .toLowerCase ( ) = "s" and
1204
1220
len =
@@ -1218,6 +1234,10 @@ class FormatLiteral extends Literal {
1218
1234
* determining whether a buffer overflow is caused by long float to string
1219
1235
* conversions.
1220
1236
*/
1237
+ int getMaxConvertedLengthLimited ( int n ) {
1238
+ result = max ( int l | l = getMaxConvertedLengthLimited ( n , _) | l )
1239
+ }
1240
+
1221
1241
int getMaxConvertedLengthLimited ( int n , BufferWriteEstimationReason reason ) {
1222
1242
if this .getConversionChar ( n ) .toLowerCase ( ) = "f"
1223
1243
then result = this .getMaxConvertedLength ( n , reason ) .minimum ( 8 )
@@ -1269,20 +1289,20 @@ class FormatLiteral extends Literal {
1269
1289
result =
1270
1290
this .getConstantPart ( n ) .length ( ) + this .getMaxConvertedLength ( n , headReason ) +
1271
1291
this .getMaxConvertedLengthAfter ( n + 1 , tailReason ) and
1272
- reason = headReason .combineWith ( tailReason )
1292
+ reason = headReason .combineWith ( tailReason )
1273
1293
)
1274
1294
}
1275
1295
1276
1296
private int getMaxConvertedLengthAfterLimited ( int n , BufferWriteEstimationReason reason ) {
1277
1297
if n = this .getNumConvSpec ( )
1278
1298
then result = this .getConstantSuffix ( ) .length ( ) + 1 and reason = TValueFlowAnalysis ( )
1279
1299
else
1280
- exists ( BufferWriteEstimationReason headReason , BufferWriteEstimationReason tailReason |
1281
- result =
1282
- this .getConstantPart ( n ) .length ( ) + this .getMaxConvertedLengthLimited ( n , headReason ) +
1283
- this .getMaxConvertedLengthAfterLimited ( n + 1 , tailReason ) and
1284
- reason = headReason .combineWith ( tailReason )
1285
- )
1300
+ exists ( BufferWriteEstimationReason headReason , BufferWriteEstimationReason tailReason |
1301
+ result =
1302
+ this .getConstantPart ( n ) .length ( ) + this .getMaxConvertedLengthLimited ( n , headReason ) +
1303
+ this .getMaxConvertedLengthAfterLimited ( n + 1 , tailReason ) and
1304
+ reason = headReason .combineWith ( tailReason )
1305
+ )
1286
1306
}
1287
1307
1288
1308
/**
0 commit comments