Signed overflow check¶
ID: cpp/signed-overflow-checkKind: problemSecurity severity: 8.1Severity: warningPrecision: highTags: - correctness - security - external/cwe/cwe-128 - external/cwe/cwe-190Query suites: - cpp-code-scanning.qls - cpp-security-extended.qls - cpp-security-and-quality.qls
Click to see the query in the CodeQL repository
When checking for integer overflow, you may often write tests likea+b<a. This works fine ifa orb are unsigned integers, since any overflow in the addition will cause the value to simply “wrap around.” However, usingsigned integers is problematic because signed overflow has undefined behavior according to the C and C++ standards. If the addition overflows and has an undefined result, the comparison will likewise be undefined; it may produce an unintended result, or may be deleted entirely by an optimizing compiler.
Recommendation¶
Solutions to this problem can be thought of as falling into one of two categories:
Rewrite the signed expression so that overflow cannot occur but the signedness remains.
Change the variables and all their uses to be unsigned.The following cases all fall into the first category.
Given
unsignedshortn1,deltaandn1+delta<n1, it is possible to rewrite it as(unsignedshort)(n1+delta) < n1. Note thatn1+deltadoes not actually overflow, due tointpromotion.Given
unsignedshortn1,deltaandn1+delta<n1, it is also possible to rewrite it asn1>USHORT_MAX-delta. Thelimits.horclimitsheader must then be included.Given
intn1,deltaandn1+delta<n1, it is possible to rewrite it asn1>INT_MAX-delta. It must be true thatdelta>=0and thelimits.horclimitsheader has been included.
Example¶
In the following example, even thoughdelta has been declaredunsignedshort, C/C++ type promotion rules require that its type is promoted to the larger type used in the addition and comparison, namely asignedint. Addition is performed on signed integers, and may have undefined behavior if an overflow occurs. As a result, the entire (comparison) expression may also have an undefined result.
boolfoo(intn1,unsignedshortdelta){returnn1+delta<n1;// BAD}
The following example builds upon the previous one. Instead of performing an addition (which could overflow), we have re-framed the solution so that a subtraction is used instead. Sincedelta is promoted to asignedint andINT_MAX denotes the largest possible positive value for ansignedint, the expressionINT_MAX-delta can never be less than zero or more thanINT_MAX. Hence, any overflow and underflow are avoided.
#include<limits.h>boolfoo(intn1,unsignedshortdelta){returnn1>INT_MAX-delta;// GOOD}
In the following example, even though bothn anddelta have been declaredunsignedshort, both are promoted tosignedint prior to addition. Because we started out with the narrowershort type, the addition is guaranteed not to overflow and is therefore defined. But the fact thatn1+delta never overflows means that the conditionn1+delta<n1 will never hold true, which likely is not what the programmer intended. (see also thecpp/bad-addition-overflow-check query).
boolbar(unsignedshortn1,unsignedshortdelta){// NB: Comparison is always falsereturnn1+delta<n1;// GOOD (but misleading)}
The next example provides a solution to the previous one. Even thoughn1+delta does not overflow, casting it to anunsignedshort truncates the addition modulo 2^16, so thatunsignedshort “wrap around” may now be observed. Furthermore, since the left-hand side is now of typeunsignedshort, the right-hand side does not need to be promoted to asignedint.
boolbar(unsignedshortn1,unsignedshortdelta){return(unsignedshort)(n1+delta)<n1;// GOOD}
References¶
INT31-C. Ensure that integer conversions do not result in lost or misinterpreted data
W. Dietz, P. Li, J. Regehr, V. Adve.Understanding Integer Overflow in C/C++
Common Weakness Enumeration:CWE-128.
Common Weakness Enumeration:CWE-190.