Add ovf tests and more overflow macro definitions ##util (#17216)
This commit is contained in:
parent
a034b99484
commit
b25c3275de
|
@ -380,19 +380,6 @@ static inline void *r_new_copy(int size, void *data) {
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#define R_BETWEEN(x,y,z) (((y)>=(x)) && ((y)<=(z)))
|
||||
#define R_ROUND(x,y) ((x)%(y))?(x)+((y)-((x)%(y))):(x)
|
||||
#define R_DIM(x,y,z) (((x)<(y))?(y):((x)>(z))?(z):(x))
|
||||
#ifndef R_MAX_DEFINED
|
||||
#define R_MAX(x,y) (((x)>(y))?(x):(y))
|
||||
#define R_MAX_DEFINED
|
||||
#endif
|
||||
#ifndef R_MIN_DEFINED
|
||||
#define R_MIN(x,y) (((x)>(y))?(y):(x))
|
||||
#define R_MIN_DEFINED
|
||||
#endif
|
||||
#define R_ABS(x) (((x)<0)?-(x):(x))
|
||||
#define R_BTW(x,y,z) (((x)>=(y))&&((y)<=(z)))?y:x
|
||||
|
||||
#define R_FREE(x) { free((void *)x); x = NULL; }
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define R2_TYPES_BASE_H
|
||||
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define cut8 const unsigned char
|
||||
#define ut64 unsigned long long
|
||||
|
@ -50,7 +51,7 @@ typedef struct _ut256 {
|
|||
ut128 Low;
|
||||
ut128 High;
|
||||
} ut256;
|
||||
typedef struct _utX{
|
||||
typedef struct _utX {
|
||||
ut80 v80;
|
||||
ut96 v96;
|
||||
ut128 v128;
|
||||
|
@ -69,8 +70,8 @@ typedef struct _utX{
|
|||
#undef UT64_MIN
|
||||
#undef UT32_MAX
|
||||
#undef UT32_MIN
|
||||
#define ST64_MAX 0x7FFFFFFFFFFFFFFFULL
|
||||
#define ST64_MIN (-ST64_MAX-1)
|
||||
#define ST64_MAX ((st64)0x7FFFFFFFFFFFFFFFULL)
|
||||
#define ST64_MIN ((st64)(-ST64_MAX-1))
|
||||
#define UT64_MAX 0xFFFFFFFFFFFFFFFFULL
|
||||
#define UT64_GT0 0x8000000000000000ULL
|
||||
#define UT64_LT0 0x7FFFFFFFFFFFFFFFULL
|
||||
|
@ -97,6 +98,18 @@ typedef struct _utX{
|
|||
#define ASCII_MIN 32
|
||||
#define ASCII_MAX 127
|
||||
|
||||
#if SSIZE_MAX == ST32_MAX
|
||||
#define SZT_MAX UT32_MAX
|
||||
#define SZT_MIN UT32_MIN
|
||||
#define SSZT_MAX ST32_MAX
|
||||
#define SSZT_MIN ST32_MIN
|
||||
#else
|
||||
#define SZT_MAX UT64_MAX
|
||||
#define SZT_MIN UT64_MIN
|
||||
#define SSZT_MAX ST64_MAX
|
||||
#define SSZT_MIN ST64_MIN
|
||||
#endif
|
||||
|
||||
#define UT64_ALIGN(x) (x + (x - (x % sizeof (ut64))))
|
||||
#define UT32_ALIGN(x) (x + (x - (x % sizeof (ut32))))
|
||||
#define UT16_ALIGN(x) (x + (x - (x % sizeof (ut16))))
|
||||
|
@ -104,22 +117,29 @@ typedef struct _utX{
|
|||
#define UT32_LO(x) ((ut32)((x)&UT32_MAX))
|
||||
#define UT32_HI(x) ((ut32)(((ut64)(x))>>32)&UT32_MAX)
|
||||
|
||||
/* preventive math overflow checks */
|
||||
#if !defined(SZT_ADD_OVFCHK)
|
||||
#define SZT_ADD_OVFCHK(x,y) ((SIZE_MAX - (x)) < (y))
|
||||
#define R_BETWEEN(x,y,z) (((y)>=(x)) && ((y)<=(z)))
|
||||
#define R_ROUND(x,y) ((x)%(y))?(x)+((y)-((x)%(y))):(x)
|
||||
#define R_DIM(x,y,z) (((x)<(y))?(y):((x)>(z))?(z):(x))
|
||||
#ifndef R_MAX_DEFINED
|
||||
#define R_MAX(x,y) (((x)>(y))?(x):(y))
|
||||
#define R_MAX_DEFINED
|
||||
#endif
|
||||
#define UT64_ADD_OVFCHK(x,y) ((UT64_MAX - (x)) < (y))
|
||||
#define UT32_ADD_OVFCHK(x,y) ((UT32_MAX - (x)) < (y))
|
||||
#define UT16_ADD_OVFCHK(x,y) ((UT16_MAX - (x)) < (y))
|
||||
#define UT8_ADD_OVFCHK(x,y) ((UT8_MAX - (x)) < (y))
|
||||
#ifndef R_MIN_DEFINED
|
||||
#define R_MIN(x,y) (((x)>(y))?(y):(x))
|
||||
#define R_MIN_DEFINED
|
||||
#endif
|
||||
#define R_ABS(x) (((x)<0)?-(x):(x))
|
||||
#define R_BTW(x,y,z) (((x)>=(y))&&((y)<=(z)))?y:x
|
||||
|
||||
#include "r_types_overflow.h"
|
||||
|
||||
/* copied from bithacks.h */
|
||||
#define B_IS_SET(x, n) (((x) & (1ULL<<(n)))?1:0)
|
||||
#define B_SET(x, n) ((x) |= (1ULL<<(n)))
|
||||
#define B_EVEN(x) (((x)&1)==0)
|
||||
#define B_IS_SET(x, n) (((x) & (1ULL << (n)))? 1: 0)
|
||||
#define B_SET(x, n) ((x) |= (1ULL << (n)))
|
||||
#define B_EVEN(x) (((x) & 1) == 0)
|
||||
#define B_ODD(x) (!B_EVEN((x)))
|
||||
#define B_UNSET(x, n) ((x) &= ~(1ULL<<(n)))
|
||||
#define B_TOGGLE(x, n) ((x) ^= (1ULL<<(n)))
|
||||
#define B_UNSET(x, n) ((x) &= ~(1ULL << (n)))
|
||||
#define B_TOGGLE(x, n) ((x) ^= (1ULL << (n)))
|
||||
|
||||
#define B1111 15
|
||||
#define B1110 14
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
#ifndef R_TYPES_OVERFLOW_H
|
||||
#define R_TYPES_OVERFLOW_H
|
||||
|
||||
// TODO: Use CLANG/GCC builtins if available: __builtin_mul_overflow
|
||||
|
||||
// ADD
|
||||
// if ((x > 0) && (a > INT_MAX - x)) /* `a + x` would overflow */;
|
||||
// if ((x < 0) && (a < INT_MIN - x)) /* `a + x` would underflow */;
|
||||
#define SZT_ADD_OVFCHK(x,y) ((SIZE_MAX - (x)) < (y))
|
||||
#define SSZT_ADD_OVFCHK(a,x) ((((x) > 0) && ((a) > SSIZE_MAX - (x))) || (((x) < 0) && (a) < SSIZE_MIN - (x)))
|
||||
#define UT64_ADD_OVFCHK(x,y) ((UT64_MAX - (x)) < (y))
|
||||
#define ST64_ADD_OVFCHK(a,x) ((((x) > 0) && ((a) > ST64_MAX - (x))) || (((x) < 0) && (a) < ST64_MIN - (x)))
|
||||
#define UT32_ADD_OVFCHK(x,y) ((UT32_MAX - (x)) < (y))
|
||||
#define ST32_ADD_OVFCHK(a,x) ((((x) > 0) && ((a) > ST32_MAX - (x))) || (((x) < 0) && (a) < ST32_MIN - (x)))
|
||||
#define UT16_ADD_OVFCHK(x,y) ((UT16_MAX - (x)) < (y))
|
||||
#define ST16_ADD_OVFCHK(a,b) ((((b) > 0) && ((a) > ST16_MAX - (b))) || (((b) < 0) && ((a) < ST16_MIN - (b))))
|
||||
#define UT8_ADD_OVFCHK(x,y) ((UT8_MAX - (x)) < (y))
|
||||
#define ST8_ADD_OVFCHK(a,x) ((((x) > 0) && ((a) > ST8_MAX - (x))) || ((x) < 0 && (a) < ST8_MIN - (x)))
|
||||
|
||||
// SUB
|
||||
// if ((x < 0) && (a > INT_MAX + x)) /* `a - x` would overflow */;
|
||||
// if ((x > 0) && (a < INT_MIN + x)) /* `a - x` would underflow */;
|
||||
#define SZT_SUB_OVFCHK(a,b) SZT_ADD_OVFCHK(a,-(b))
|
||||
#define SSZT_SUB_OVFCHK(a,b) SSZT_ADD_OVFCHK(a,-(b))
|
||||
#define UT64_SUB_OVFCHK(a,b) UT64_ADD_OVFCHK(a,-(b))
|
||||
#define ST64_SUB_OVFCHK(a,b) ST64_ADD_OVFCHK(a,-(b))
|
||||
#define UT32_SUB_OVFCHK(a,b) UT32_ADD_OVFCHK(a,-(b))
|
||||
#define ST32_SUB_OVFCHK(a,b) ST32_ADD_OVFCHK(a,-(b))
|
||||
#define UT16_SUB_OVFCHK(a,b) UT16_ADD_OVFCHK(a,-(b))
|
||||
#define ST16_SUB_OVFCHK(a,b) ST16_ADD_OVFCHK(a,-(b))
|
||||
#define UT8_SUB_OVFCHK(a,b) UT8_ADD_OVFCHK(a,-(b))
|
||||
#define ST8_SUB_OVFCHK(a,b) ST8_ADD_OVFCHK(a,-(b))
|
||||
|
||||
// MUL
|
||||
#define UNSIGNED_MUL_OVERFLOW_CHECK(overflow_name, type_base, type_min, type_max) \
|
||||
static inline bool overflow_name(type_base a, type_base b) { \
|
||||
return (a > 0 && b > 0 && a > type_max / b); \
|
||||
}
|
||||
|
||||
#define SIGNED_MUL_OVERFLOW_CHECK(overflow_name, type_base, type_min, type_max) \
|
||||
static inline bool overflow_name(type_base a, type_base b) { \
|
||||
if (a > 0) { \
|
||||
if (b > 0) { return a > type_max / b; } \
|
||||
return b < type_min / a; \
|
||||
} \
|
||||
if (b > 0) { return a < type_min / b; } \
|
||||
return a && b < type_max / a; \
|
||||
}
|
||||
|
||||
// TODO: Windows doesn't have ssize_t, and we don't need this check yet
|
||||
// SIGNED_MUL_OVERFLOW_CHECK(SSZT_MUL_OVFCHK, ssize_t, SSZT_MIN, SSZT_MAX)
|
||||
SIGNED_MUL_OVERFLOW_CHECK(ST8_MUL_OVFCHK, st8, ST8_MIN, ST8_MAX)
|
||||
SIGNED_MUL_OVERFLOW_CHECK(ST16_MUL_OVFCHK, st16, ST16_MIN, ST16_MAX)
|
||||
SIGNED_MUL_OVERFLOW_CHECK(ST32_MUL_OVFCHK, st32, ST32_MIN, ST32_MAX)
|
||||
SIGNED_MUL_OVERFLOW_CHECK(ST64_MUL_OVFCHK, st64, ST64_MIN, ST64_MAX)
|
||||
UNSIGNED_MUL_OVERFLOW_CHECK(SZT_MUL_OVFCHK, size_t, SZT_MIN, SZT_MAX)
|
||||
UNSIGNED_MUL_OVERFLOW_CHECK(UT8_MUL_OVFCHK, ut8, UT8_MIN, UT8_MAX)
|
||||
UNSIGNED_MUL_OVERFLOW_CHECK(UT16_MUL_OVFCHK, ut16, UT16_MIN, UT16_MAX)
|
||||
UNSIGNED_MUL_OVERFLOW_CHECK(UT32_MUL_OVFCHK, ut32, UT32_MIN, UT32_MAX)
|
||||
UNSIGNED_MUL_OVERFLOW_CHECK(UT64_MUL_OVFCHK, ut64, UT64_MIN, UT64_MAX)
|
||||
|
||||
#endif
|
|
@ -375,6 +375,7 @@ include_files =[
|
|||
'include/r_socket.h',
|
||||
'include/r_syscall.h',
|
||||
'include/r_th.h',
|
||||
'include/r_types_overflow.h',
|
||||
'include/r_types_base.h',
|
||||
'include/r_types.h',
|
||||
'include/r_util.h',
|
||||
|
|
|
@ -14,6 +14,7 @@ if get_option('enable_tests')
|
|||
'bin',
|
||||
'bitmap',
|
||||
'buf',
|
||||
'ovf',
|
||||
'cmd',
|
||||
'r2pipe',
|
||||
'cons',
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/* radare2 - LGPL - Copyright 2020 - pancake */
|
||||
|
||||
#include <r_util.h>
|
||||
#include "minunit.h"
|
||||
|
||||
int test_overflow_add(void) {
|
||||
mu_assert_true (UT8_ADD_OVFCHK (250, 32), "ut8-add 1");
|
||||
mu_assert_false (UT8_ADD_OVFCHK (250, 2), "ut8-add 2");
|
||||
mu_assert_false (UT16_ADD_OVFCHK (ST16_MAX, 2), "ut16-add 2");
|
||||
mu_assert_true (ST16_ADD_OVFCHK (ST16_MAX, 2), "st16-add 2");
|
||||
mu_assert_true (ST16_ADD_OVFCHK (ST16_MAX - 2, 4), "st16-add 2");
|
||||
mu_assert_true (ST16_ADD_OVFCHK (1, ST16_MAX), "st16-add 3");
|
||||
|
||||
mu_assert_true (ST16_ADD_OVFCHK (ST16_MIN, -1), "st16-add (min, -1)");
|
||||
mu_assert_true (UT16_ADD_OVFCHK (10, -20), "ut16-add (10, -20)");
|
||||
mu_assert_false (ST16_ADD_OVFCHK (-10, 20), "st16-add (-10, 20)");
|
||||
mu_assert_true (ST32_ADD_OVFCHK (ST32_MIN, -20), "st32-add (min, -20)");
|
||||
mu_assert_false (ST32_ADD_OVFCHK (-10, 20), "st32-add (-10, 20)");
|
||||
mu_assert_true (ST64_ADD_OVFCHK (ST64_MIN, -20), "st64-add (min, -20)");
|
||||
mu_assert_false (ST64_ADD_OVFCHK (-10, 20), "st64-add 3");
|
||||
mu_end;
|
||||
}
|
||||
|
||||
int test_underflow_sub(void) {
|
||||
mu_assert_false (ST16_SUB_OVFCHK (10, 210), "st16-sub-sign-underflow");
|
||||
mu_assert_true (UT16_SUB_OVFCHK (10, 210), "ut16-sub-underflow");
|
||||
mu_assert_true (ST16_SUB_OVFCHK (ST16_MIN, 210), "st16-sub-underflow");
|
||||
mu_end;
|
||||
}
|
||||
|
||||
int test_underflow_add(void) {
|
||||
mu_assert_false (ST16_SUB_OVFCHK (10, -210), "st16-sub");
|
||||
mu_assert_false (ST16_SUB_OVFCHK (10, 10), "st16-sub 10");
|
||||
mu_assert_true (ST16_SUB_OVFCHK (ST16_MIN, 11), "st16-sub 10-11");
|
||||
mu_assert_false (ST16_SUB_OVFCHK (10, 11), "st16-sub 10-11");
|
||||
mu_assert_true (UT16_SUB_OVFCHK (10, 11), "ut16-sub 10-11");
|
||||
mu_end;
|
||||
}
|
||||
|
||||
int test_overflow_mul(void) {
|
||||
mu_assert_true (UT8_MUL_OVFCHK (16, 32), "ut8-mul");
|
||||
mu_assert_false (UT8_MUL_OVFCHK (16, 2), "ut8-mul 2");
|
||||
mu_assert_true (ST8_MUL_OVFCHK (16, 100), "st8-mul 3");
|
||||
mu_assert_false (ST8_MUL_OVFCHK (16, 1), "st8-mul 4");
|
||||
mu_assert_false (ST8_MUL_OVFCHK (-2, 2), "st8-mul sign overflow");
|
||||
mu_assert_false (ST8_MUL_OVFCHK (-1, 1), "st8-mul sign overflow");
|
||||
mu_assert_false (ST8_MUL_OVFCHK (1, -1), "st8-mul sign overflow");
|
||||
mu_assert_false (ST8_MUL_OVFCHK (2, -2), "st8-mul sign overflow");
|
||||
mu_assert_false (ST8_MUL_OVFCHK (-1, -2), "st8-mul sign overflow");
|
||||
mu_assert_false (ST8_MUL_OVFCHK (-2, -1), "st8-mul sign overflow");
|
||||
mu_assert_true (ST8_MUL_OVFCHK (-16, 100), "st8-mul sign overflow");
|
||||
mu_assert_true (ST8_MUL_OVFCHK (100, -16), "st8-mul sign overflow");
|
||||
mu_assert_false (ST8_MUL_OVFCHK (3, -16), "st8-mul sign overflow");
|
||||
mu_end;
|
||||
}
|
||||
|
||||
int test_overflow_mul2(void) {
|
||||
mu_assert_false (ST8_MUL_OVFCHK (-1, 0), "st8-mul2 -1 0");
|
||||
mu_assert_false (ST8_MUL_OVFCHK (1, 0), "st8-mul2 -1 0");
|
||||
mu_end;
|
||||
}
|
||||
|
||||
int all_tests() {
|
||||
mu_run_test (test_overflow_add);
|
||||
mu_run_test (test_underflow_add);
|
||||
mu_run_test (test_underflow_sub);
|
||||
mu_run_test (test_overflow_mul);
|
||||
mu_run_test (test_overflow_mul2);
|
||||
return tests_passed != tests_run;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
return all_tests ();
|
||||
}
|
Loading…
Reference in New Issue