Add division overflow macros in r_types ##util (#17856)

This commit is contained in:
pancake 2020-10-30 05:42:32 +01:00 committed by Florian Märkl
parent 8a319a2b09
commit 7b171b9961
3 changed files with 22 additions and 14 deletions

View file

@ -1540,18 +1540,6 @@ static bool esil_mod(RzAnalEsil *esil) {
return ret;
}
static bool detect_fpu_div_exception(ut64 a, ut64 b) {
// division by zero
if (b == UT64_MIN) {
return true;
}
// undefined result (0x80000 / -1) cant be represented
if (a == UT64_GT0 && b == UT64_MAX) {
return true;
}
return false;
}
static bool esil_signed_mod(RzAnalEsil *esil) {
bool ret = false;
st64 s, d;
@ -1559,7 +1547,7 @@ static bool esil_signed_mod(RzAnalEsil *esil) {
char *src = rz_anal_esil_pop (esil);
if (src && rz_anal_esil_get_parm (esil, src, (ut64 *)&s)) {
if (dst && rz_anal_esil_get_parm (esil, dst, (ut64 *)&d)) {
if (detect_fpu_div_exception (d, s)) {
if (ST64_DIV_OVFCHK (d, s)) {
if (esil->verbose > 0) {
eprintf ("0x%08"PFMT64x" esil_mod: Division by zero!\n", esil->address);
}
@ -1638,7 +1626,7 @@ static bool esil_signed_div(RzAnalEsil *esil) {
char *src = rz_anal_esil_pop (esil);
if (src && rz_anal_esil_get_parm (esil, src, (ut64 *)&s)) {
if (dst && rz_anal_esil_get_parm (esil, dst, (ut64 *)&d)) {
if (detect_fpu_div_exception (d, s)) {
if (ST64_DIV_OVFCHK (d, s)) {
ERR ("esil_div: Division by zero!");
esil->trap = RZ_ANAL_TRAP_DIVBYZERO;
esil->trap_code = 0;

View file

@ -70,6 +70,8 @@ typedef struct _utX {
#undef UT64_MIN
#undef UT32_MAX
#undef UT32_MIN
#undef UT16_MIN
#undef UT8_MIN
#define ST64_MAX ((st64)0x7FFFFFFFFFFFFFFFULL)
#define ST64_MIN ((st64)(-ST64_MAX-1))
#define UT64_MAX 0xFFFFFFFFFFFFFFFFULL
@ -80,6 +82,7 @@ typedef struct _utX {
#define UT64_16U 0xFFFFFFFFFFFF0000ULL
#define UT64_8U 0xFFFFFFFFFFFFFF00ULL
#define UT32_MIN 0U
#define UT16_MIN 0U
#define UT32_GT0 0x80000000U
#define UT32_LT0 0x7FFFFFFFU
#define ST32_MAX 0x7FFFFFFF

View file

@ -47,6 +47,23 @@ static inline bool overflow_name(type_base a, type_base b) { \
return a && b < type_max / a; \
}
#define SIGNED_DIV_OVERFLOW_CHECK(overflow_name, type_base, type_mid, type_max) \
static inline bool overflow_name(type_base a, type_base b) { \
return (!b || (a == type_mid && b == type_max)); \
}
#define UNSIGNED_DIV_OVERFLOW_CHECK(overflow_name, type_base, type_min, type_max) \
static inline bool overflow_name(type_base a, type_base b) { \
return !b; \
}
SIGNED_DIV_OVERFLOW_CHECK(ST8_DIV_OVFCHK, ut8, UT8_GT0, UT8_MAX)
SIGNED_DIV_OVERFLOW_CHECK(ST16_DIV_OVFCHK, ut16, UT16_GT0, UT16_MAX)
SIGNED_DIV_OVERFLOW_CHECK(ST32_DIV_OVFCHK, ut32, UT32_GT0, UT32_MAX)
SIGNED_DIV_OVERFLOW_CHECK(ST64_DIV_OVFCHK, ut64, UT64_GT0, UT64_MAX)
UNSIGNED_DIV_OVERFLOW_CHECK(UT8_DIV_OVFCHK, ut8, UT8_MIN, UT8_MAX)
UNSIGNED_DIV_OVERFLOW_CHECK(UT16_DIV_OVFCHK, ut16, UT16_MIN, UT16_MAX)
UNSIGNED_DIV_OVERFLOW_CHECK(UT32_DIV_OVFCHK, ut32, UT32_MIN, UT32_MAX)
UNSIGNED_DIV_OVERFLOW_CHECK(UT64_DIV_OVFCHK, ut64, UT64_MIN, UT64_MAX)
// 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)