Reputation: 121
Generally, How can I prevent integer overflow from happening in C programming language? I mean, Is there any functions to prevent? And finally, Is integer overflow going to get me hacked like buffer overflow or etc?
Upvotes: 11
Views: 23670
Reputation: 52538
Assume you have two int values a, b, and you want to check that a+b doesn't produce overflow or underflow.
There are two cases: a ≥ 0 and a ≤ 0. In the first case, you cannot have underflow. You have overflow if b > INT_MAX - a. In the second case, you cannot have overflow. You can have underflow if b < INT_MIN - a. As a single expression:
a >= 0 ? b > INT_MAX - a : b < INT_MIN - a
Upvotes: 9
Reputation: 213809
Whenever you declare an integer variable:
intn_t
or uintn_t
types from stdint.h
that will satisfy the above (or the ...fast_t
etc flavours if you wish).That is, don't just aimlessly spam int
all over your code without a thought.
Signed types can be problematic for other reasons than overflow too, namely whenever you need to do bitwise arithmetic. To avoid over/underflow and accidental signed bitwise arithmetic, you also need to know of the various implicit integer type promotion rules.
Is integer overflow going to get me hacked like buffer overflow or etc?
Not really, but any bug can of course be exploited if someone is aware of it - as you can see in almost every single computer game.
Upvotes: 3
Reputation: 15042
You cannot prevent integer-overflow completely. If it happens, it happens. You need to be carefully at coding in the first place.
But you can try to check before the assignment if an overflow can occur.
In the case of the assignment to an object of type int
or long int
, a portable approach to check for integer-overflow would be to assign the value first to an object of type long long int
.
Then compare the stored value if is greater than INT_MAX
or less than INT_MIN
in the case of int
or greater than LONG_MAX
or less than LONG_MIN
in the case of long int
.
If it is, you know it is out of range and you can prevent the integer-overflow that way.
You can encapsulate this technique into an own custom functions if you want to use functions instead, f.e.:
#include <limits.h>
// For int.
_Bool INT_OF_CHECK (long long int n)
{
return ( n > INT_MAX || n < INT_MIN ) ? 1 : 0;
}
// For long int.
_Bool LINT_OF_CHECK (long long int n)
{
return ( n > LONG_MAX || n < LONG_MIN ) ? 1 : 0;
}
The function returns 1
if the value does not fit into the range, 0
if it does.
Unfortunately this checking method doesn't work for assignments to long long int
itself, but for int
as well as long int
it might help.
It also has the downside that it doesn't cover the case, when the value to be assigned is even greater or less than inside of the range an long long int
can hold, whereas an overflow occurs here itself, but it is just a possible approach.
The macros you can find in the header limits.h
.
Upvotes: -1
Reputation: 113
If you want to guarantee that you won't have overflows but are fine with a bit of a performance cost, look into arbitrary-precision arithmetic libraries (for example tiny-bignum-c, or GNU Multiple Precision Arithmetic).
Since C99: standard library math functions report overflow by setting errno = ERANGE
, so you can check for that (remember to set errno = 0
before calling said math function). math.h
defines HUGE_VAL
and related macros which you can check against for overflow, and for floating point errors there's the fenv
family of functions, see the manuals about math_error(7) and fenv(3).
Upvotes: 0
Reputation: 67476
Check before operation if the result will overflow.
gcc provides some helper built-in functions.
Built-in Function: bool __builtin_add_overflow (type1 a, type2 b, type3 *res)
Built-in Function: bool __builtin_sadd_overflow (int a, int b, int *res)
Built-in Function: bool __builtin_saddl_overflow (long int a, long int b, long int *res)
Built-in Function: bool __builtin_saddll_overflow (long long int a, long long int b, long long int *res)
Built-in Function: bool __builtin_uadd_overflow (unsigned int a, unsigned int b, unsigned int *res)
Built-in Function: bool __builtin_uaddl_overflow (unsigned long int a, unsigned long int b, unsigned long int *res)
Built-in Function: bool __builtin_uaddll_overflow (unsigned long long int a, unsigned long long int b, unsigned long long int *res)
These built-in functions promote the first two operands into infinite precision signed type and perform addition on those promoted operands. The result is then cast to the type the third pointer argument points to and stored there. If the stored result is equal to the infinite precision result, the built-in functions return false, otherwise they return true. As the addition is performed in infinite signed precision, these built-in functions have fully defined behavior for all argument values.
The first built-in function allows arbitrary integral types for operands and the result type must be pointer to some integral type other than enumerated or boolean type, the rest of the built-in functions have explicit integer types.
The compiler will attempt to use hardware instructions to implement these built-in functions where possible, like conditional jump on overflow after addition, conditional jump on carry etc.
Built-in Function: bool __builtin_sub_overflow (type1 a, type2 b, type3 *res)
Built-in Function: bool __builtin_ssub_overflow (int a, int b, int *res)
Built-in Function: bool __builtin_ssubl_overflow (long int a, long int b, long int *res)
Built-in Function: bool __builtin_ssubll_overflow (long long int a, long long int b, long long int *res)
Built-in Function: bool __builtin_usub_overflow (unsigned int a, unsigned int b, unsigned int *res)
Built-in Function: bool __builtin_usubl_overflow (unsigned long int a, unsigned long int b, unsigned long int *res)
Built-in Function: bool __builtin_usubll_overflow (unsigned long long int a, unsigned long long int b, unsigned long long int *res)
These built-in functions are similar to the add overflow checking built-in functions above, except they perform subtraction, subtract the second argument from the first one, instead of addition.
Built-in Function: bool __builtin_mul_overflow (type1 a, type2 b, type3 *res)
Built-in Function: bool __builtin_smul_overflow (int a, int b, int *res)
Built-in Function: bool __builtin_smull_overflow (long int a, long int b, long int *res)
Built-in Function: bool __builtin_smulll_overflow (long long int a, long long int b, long long int *res)
Built-in Function: bool __builtin_umul_overflow (unsigned int a, unsigned int b, unsigned int *res)
Built-in Function: bool __builtin_umull_overflow (unsigned long int a, unsigned long int b, unsigned long int *res)
Built-in Function: bool __builtin_umulll_overflow (unsigned long long int a, unsigned long long int b, unsigned long long int *res)
These built-in functions are similar to the add overflow checking built-in functions above, except they perform multiplication, instead of addition.
The following built-in functions allow checking if simple arithmetic operation would overflow.
Built-in Function: bool __builtin_add_overflow_p (type1 a, type2 b, type3 c)
Built-in Function: bool __builtin_sub_overflow_p (type1 a, type2 b, type3 c)
Built-in Function: bool __builtin_mul_overflow_p (type1 a, type2 b, type3 c)
Integer overflow itself is an UB and it may lead to many problems. But it depends of your code. If it is not the part if the pointer arithmetic or array indexing you will not be "hacked"
Upvotes: 3