@@ -399,6 +399,18 @@ private BufferWriteEstimationReason getEstimationReasonForIntegralExpression(Exp
399399 else result = TTypeBoundsAnalysis ( )
400400}
401401
402+ /**
403+ * Gets the number of hex digits required to represent the integer represented by `f`.
404+ *
405+ * `f` is assumed to be nonnegative.
406+ */
407+ bindingset [ f]
408+ private int lengthInBase16 ( float f ) {
409+ f = 0 and result = 1
410+ or
411+ result = ( f .log2 ( ) / 4.0 ) .floor ( ) + 1
412+ }
413+
402414/**
403415 * A class to represent format strings that occur as arguments to invocations of formatting functions.
404416 */
@@ -1253,23 +1265,42 @@ class FormatLiteral extends Literal {
12531265 or
12541266 this .getConversionChar ( n ) .toLowerCase ( ) = "x" and
12551267 // e.g. "12345678"
1256- exists ( int sizeBytes , int baseLen |
1257- sizeBytes =
1258- min ( int bytes |
1259- bytes = this .getIntegralDisplayType ( n ) .getSize ( )
1268+ exists ( int baseLen , int typeBasedBound , int valueBasedBound |
1269+ typeBasedBound =
1270+ min ( int digits |
1271+ digits = 2 * this .getIntegralDisplayType ( n ) .getSize ( )
12601272 or
12611273 exists ( IntegralType t |
12621274 t = this .getUse ( ) .getConversionArgument ( n ) .getType ( ) .getUnderlyingType ( )
12631275 |
1264- t .isUnsigned ( ) and bytes = t .getSize ( )
1276+ t .isUnsigned ( ) and
1277+ digits = 2 * t .getSize ( )
12651278 )
12661279 ) and
1267- baseLen = sizeBytes * 2 and
1268- (
1269- if this .hasAlternateFlag ( n ) then len = 2 + baseLen else len = baseLen // "0x"
1270- )
1271- ) and
1272- reason = TTypeBoundsAnalysis ( )
1280+ exists ( Expr arg , float lower , float upper , float typeLower , float typeUpper |
1281+ arg = this .getUse ( ) .getConversionArgument ( n ) and
1282+ lower = lowerBound ( arg .getFullyConverted ( ) ) and
1283+ upper = upperBound ( arg .getFullyConverted ( ) ) and
1284+ typeLower = exprMinVal ( arg .getFullyConverted ( ) ) and
1285+ typeUpper = exprMaxVal ( arg .getFullyConverted ( ) )
1286+ |
1287+ valueBasedBound =
1288+ lengthInBase16 ( max ( float cand |
1289+ // If lower can be negative we use `(unsigned)-1` as the candidate value.
1290+ lower < 0 and
1291+ cand = 2 .pow ( any ( IntType t | t .isUnsigned ( ) ) .getSize ( ) * 8 )
1292+ or
1293+ cand = upper
1294+ ) ) and
1295+ (
1296+ if lower > typeLower or upper < typeUpper
1297+ then reason = TValueFlowAnalysis ( )
1298+ else reason = TTypeBoundsAnalysis ( )
1299+ )
1300+ ) and
1301+ baseLen = valueBasedBound .minimum ( typeBasedBound ) and
1302+ if this .hasAlternateFlag ( n ) then len = 2 + baseLen else len = baseLen // "0x"
1303+ )
12731304 or
12741305 this .getConversionChar ( n ) .toLowerCase ( ) = "p" and
12751306 exists ( PointerType ptrType , int baseLen |
0 commit comments