Add ovf tests and more overflow macro definitions ##util (#17216)

This commit is contained in:
pancake 2020-07-24 13:21:52 +02:00 committed by GitHub
parent a034b99484
commit b25c3275de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 173 additions and 28 deletions

View File

@ -380,19 +380,6 @@ static inline void *r_new_copy(int size, void *data) {
#endif #endif
#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; } #define R_FREE(x) { free((void *)x); x = NULL; }

View File

@ -2,6 +2,7 @@
#define R2_TYPES_BASE_H #define R2_TYPES_BASE_H
#include <ctype.h> #include <ctype.h>
#include <sys/types.h>
#define cut8 const unsigned char #define cut8 const unsigned char
#define ut64 unsigned long long #define ut64 unsigned long long
@ -50,7 +51,7 @@ typedef struct _ut256 {
ut128 Low; ut128 Low;
ut128 High; ut128 High;
} ut256; } ut256;
typedef struct _utX{ typedef struct _utX {
ut80 v80; ut80 v80;
ut96 v96; ut96 v96;
ut128 v128; ut128 v128;
@ -69,8 +70,8 @@ typedef struct _utX{
#undef UT64_MIN #undef UT64_MIN
#undef UT32_MAX #undef UT32_MAX
#undef UT32_MIN #undef UT32_MIN
#define ST64_MAX 0x7FFFFFFFFFFFFFFFULL #define ST64_MAX ((st64)0x7FFFFFFFFFFFFFFFULL)
#define ST64_MIN (-ST64_MAX-1) #define ST64_MIN ((st64)(-ST64_MAX-1))
#define UT64_MAX 0xFFFFFFFFFFFFFFFFULL #define UT64_MAX 0xFFFFFFFFFFFFFFFFULL
#define UT64_GT0 0x8000000000000000ULL #define UT64_GT0 0x8000000000000000ULL
#define UT64_LT0 0x7FFFFFFFFFFFFFFFULL #define UT64_LT0 0x7FFFFFFFFFFFFFFFULL
@ -97,6 +98,18 @@ typedef struct _utX{
#define ASCII_MIN 32 #define ASCII_MIN 32
#define ASCII_MAX 127 #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 UT64_ALIGN(x) (x + (x - (x % sizeof (ut64))))
#define UT32_ALIGN(x) (x + (x - (x % sizeof (ut32)))) #define UT32_ALIGN(x) (x + (x - (x % sizeof (ut32))))
#define UT16_ALIGN(x) (x + (x - (x % sizeof (ut16)))) #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_LO(x) ((ut32)((x)&UT32_MAX))
#define UT32_HI(x) ((ut32)(((ut64)(x))>>32)&UT32_MAX) #define UT32_HI(x) ((ut32)(((ut64)(x))>>32)&UT32_MAX)
/* preventive math overflow checks */ #define R_BETWEEN(x,y,z) (((y)>=(x)) && ((y)<=(z)))
#if !defined(SZT_ADD_OVFCHK) #define R_ROUND(x,y) ((x)%(y))?(x)+((y)-((x)%(y))):(x)
#define SZT_ADD_OVFCHK(x,y) ((SIZE_MAX - (x)) < (y)) #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 #endif
#define UT64_ADD_OVFCHK(x,y) ((UT64_MAX - (x)) < (y)) #ifndef R_MIN_DEFINED
#define UT32_ADD_OVFCHK(x,y) ((UT32_MAX - (x)) < (y)) #define R_MIN(x,y) (((x)>(y))?(y):(x))
#define UT16_ADD_OVFCHK(x,y) ((UT16_MAX - (x)) < (y)) #define R_MIN_DEFINED
#define UT8_ADD_OVFCHK(x,y) ((UT8_MAX - (x)) < (y)) #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 */ /* copied from bithacks.h */
#define B_IS_SET(x, n) (((x) & (1ULL<<(n)))?1:0) #define B_IS_SET(x, n) (((x) & (1ULL << (n)))? 1: 0)
#define B_SET(x, n) ((x) |= (1ULL<<(n))) #define B_SET(x, n) ((x) |= (1ULL << (n)))
#define B_EVEN(x) (((x)&1)==0) #define B_EVEN(x) (((x) & 1) == 0)
#define B_ODD(x) (!B_EVEN((x))) #define B_ODD(x) (!B_EVEN((x)))
#define B_UNSET(x, n) ((x) &= ~(1ULL<<(n))) #define B_UNSET(x, n) ((x) &= ~(1ULL << (n)))
#define B_TOGGLE(x, n) ((x) ^= (1ULL<<(n))) #define B_TOGGLE(x, n) ((x) ^= (1ULL << (n)))
#define B1111 15 #define B1111 15
#define B1110 14 #define B1110 14

View File

@ -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

View File

@ -375,6 +375,7 @@ include_files =[
'include/r_socket.h', 'include/r_socket.h',
'include/r_syscall.h', 'include/r_syscall.h',
'include/r_th.h', 'include/r_th.h',
'include/r_types_overflow.h',
'include/r_types_base.h', 'include/r_types_base.h',
'include/r_types.h', 'include/r_types.h',
'include/r_util.h', 'include/r_util.h',

View File

@ -14,6 +14,7 @@ if get_option('enable_tests')
'bin', 'bin',
'bitmap', 'bitmap',
'buf', 'buf',
'ovf',
'cmd', 'cmd',
'r2pipe', 'r2pipe',
'cons', 'cons',

74
test/unit/test_ovf.c Normal file
View File

@ -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 ();
}