Open kees opened 1 year ago
One of the common "wrap" patterns is if (val + offset < val) { ... }
. These can be found and replaced by Coccinelle:
@found@
unsigned long ULONG;
expression OFFSET;
@@
{
+ unsigned long sum;
...
(
- ULONG + OFFSET < ULONG
+ check_add_overflow(ULONG, OFFSET, &sum)
)
...
(
- ULONG + OFFSET
+ sum
)
...
}
And to generally locate them:
@wrap_check@
void *PTR;
unsigned long ULONG;
unsigned int UINT;
expression OFFSET;
@@
(
(
- PTR + OFFSET < PTR
+ ULONG_MAX - OFFSET > PTR
|
- ULONG + OFFSET < ULONG
+ ULONG_MAX - OFFSET > ULONG
|
- UINT + OFFSET < UINT
+ UINT_MAX - OFFSET > UINT
)
)
But this conversion results in worse code gen. It may be useful to add a wrapper macro:
#define would_add_overflow(a, b) ({ \
typeof(a) __maybe_overflowed_sum; \
check_add_overflow(a, b, &__maybe_overflowed_sum); \
})
We must mitigate all arithmetic wrap-around (overflow and underflow). This requires solving it for each of the three variable types: