diff --git a/dap-sdk/core/include/dap_math_ops.h b/dap-sdk/core/include/dap_math_ops.h index 4d16ade7f3468ecbef84f9b6d617bf882c95ccfd..a751eaae997a0a85dbe3a7b527940a032da06800 100755 --- a/dap-sdk/core/include/dap_math_ops.h +++ b/dap-sdk/core/include/dap_math_ops.h @@ -95,6 +95,9 @@ extern const uint128_t uint128_0; extern const uint128_t uint128_1; extern const uint256_t uint256_0; extern const uint256_t uint256_1; + +//todo: implement uintX_max +//extern const uint256_t uint256_max; extern const uint512_t uint512_0; static inline uint128_t GET_128_FROM_64(uint64_t n) { diff --git a/modules/common/dap_chain_common.c b/modules/common/dap_chain_common.c index 6a1c6449869d0c69a817f2f585b833b5d929b7e7..7997039a96fc270f26d8b5620f9efd5b5a8477eb 100644 --- a/modules/common/dap_chain_common.c +++ b/modules/common/dap_chain_common.c @@ -44,6 +44,8 @@ const dap_chain_net_srv_uid_t c_dap_chain_net_srv_uid_null = {0}; */ #define DAP_CHAIN$SZ_MAX128DEC DATOSHI_POW /* "340282366920938463463374607431768211455" */ #define DAP_CHAIN$SZ_MAX256DEC DATOSHI_POW256 /* 2 ^ "340282366920938463463374607431768211455" */ +#define SZ_MAX256SCINOT 83 //1.15792089237316195423570985008687907853269984665640564039457584007913129639935e77 + char *dap_cvt_uint256_to_str (uint256_t a_uint256); uint256_t dap_cvt_str_to_uint256 (const char *a_256bit_num); @@ -733,10 +735,16 @@ uint256_t dap_cvt_str_to_uint256(const char *a_256bit_num) uint256_t l_ret = uint256_0, l_nul = uint256_0; int l_strlen; char l_256bit_num[DAP_CHAIN$SZ_MAX256DEC + 1]; + int overflow_flag = 0; + + + if (!a_256bit_num) { + return log_it(L_ERROR, "NULL as an argument"), l_nul; + } /* Compute & check length */ - if ( (l_strlen = strnlen(a_256bit_num, DAP_CHAIN$SZ_MAX256DEC + 1) ) > DAP_CHAIN$SZ_MAX256DEC) - return log_it(L_ERROR, "Too many digits in `%s` (%d > %d)", a_256bit_num, l_strlen, DAP_CHAIN$SZ_MAX256DEC), l_nul; + if ( (l_strlen = strnlen(a_256bit_num, SZ_MAX256SCINOT + 1) ) > SZ_MAX256SCINOT) + return log_it(L_ERROR, "Too many digits in `%s` (%d > %d)", a_256bit_num, l_strlen, SZ_MAX256SCINOT), l_nul; /* Convert number from xxx.yyyyE+zz to xxxyyyy0000... */ char *l_eptr = strchr(a_256bit_num, 'e'); @@ -753,22 +761,33 @@ uint256_t dap_cvt_str_to_uint256(const char *a_256bit_num) if (!l_dot_ptr || l_dot_ptr > l_eptr) return log_it(L_ERROR, "Invalid number format with exponent %d", l_exp), uint256_0; int l_dot_len = l_dot_ptr - a_256bit_num; - if (l_dot_len >= DAP_CHAIN$SZ_MAX256DEC) + if (l_dot_len >= SZ_MAX256SCINOT) return log_it(L_ERROR, "Too many digits in '%s'", a_256bit_num), uint256_0; int l_exp_len = l_eptr - a_256bit_num - l_dot_len - 1; - if (l_exp_len + l_dot_len + 1 >= DAP_CHAIN$SZ_MAX256DEC) + if (l_exp_len + l_dot_len + 1 >= SZ_MAX256SCINOT) return log_it(L_ERROR, "Too many digits in '%s'", a_256bit_num), uint256_0; - if (l_exp < l_exp_len) - return log_it(L_ERROR, "Invalid number format with exponent %d and nuber coun after dot %d", l_exp, l_exp_len), uint256_0; + if (l_exp < l_exp_len) { + //todo: we need to handle numbers like 1.23456789000000e9 + return log_it(L_ERROR, "Invalid number format with exponent %d and nuber coun after dot %d", l_exp, + l_exp_len), uint256_0; + } memcpy(l_256bit_num, a_256bit_num, l_dot_len); memcpy(l_256bit_num + l_dot_len, a_256bit_num + l_dot_len + 1, l_exp_len); int l_zero_cnt = l_exp - l_exp_len; + if (l_zero_cnt > DAP_CHAIN$SZ_MAX256DEC) { + //todo: need to handle leading zeroes, like 0.000...123e100 + return log_it(L_ERROR, "Too long number for 256 bit: `%s` (%d > %d)", a_256bit_num, l_strlen, DAP_CHAIN$SZ_MAX256DEC), l_nul; + } size_t l_pos = l_dot_len + l_exp_len; for (int i = l_zero_cnt; i && l_pos < DAP_CHAIN$SZ_MAX256DEC; i--) l_256bit_num[l_pos++] = '0'; l_256bit_num[l_pos] = '\0'; l_strlen = l_pos; + } else { + //we ahve an decimal string, not sci notation + if ( (l_strlen = strnlen(a_256bit_num, DAP_CHAIN$SZ_MAX256DEC + 1) ) > DAP_CHAIN$SZ_MAX256DEC) + return log_it(L_ERROR, "Too many digits in `%s` (%d > %d)", a_256bit_num, l_strlen, DAP_CHAIN$SZ_MAX256DEC), l_nul; memcpy(l_256bit_num, a_256bit_num, l_strlen); l_256bit_num[l_strlen] = '\0'; } @@ -786,14 +805,22 @@ uint256_t dap_cvt_str_to_uint256(const char *a_256bit_num) uint256_t l_tmp; l_tmp.hi = 0; l_tmp.lo = (uint128_t)c_pow10_double[i].u64[3] * (uint128_t) l_digit; - SUM_256_256(l_ret, l_tmp, &l_ret); + overflow_flag = SUM_256_256(l_ret, l_tmp, &l_ret); + if (overflow_flag) { + //todo: change string to uint256_max after implementation + return log_it(L_ERROR, "Too big number '%s', max number is '%s'", a_256bit_num, "115792089237316195423570985008687907853269984665640564039457584007913129639935"), l_nul; + } // if (l_ret.hi == 0 && l_ret.lo == 0) { // return l_nul; // } uint128_t l_mul = (uint128_t) c_pow10_double[i].u64[2] * (uint128_t) l_digit; l_tmp.lo = l_mul << 64; l_tmp.hi = l_mul >> 64; - SUM_256_256(l_ret, l_tmp, &l_ret); + overflow_flag = SUM_256_256(l_ret, l_tmp, &l_ret); + if (overflow_flag) { + //todo: change string to uint256_max after implementation + return log_it(L_ERROR, "Too big number '%s', max number is '%s'", a_256bit_num, "115792089237316195423570985008687907853269984665640564039457584007913129639935"), l_nul; + } if (l_ret.hi == 0 && l_ret.lo == 0) { return l_nul; @@ -801,7 +828,11 @@ uint256_t dap_cvt_str_to_uint256(const char *a_256bit_num) l_tmp.lo = 0; l_tmp.hi = (uint128_t) c_pow10_double[i].u64[1] * (uint128_t) l_digit; - SUM_256_256(l_ret, l_tmp, &l_ret); + overflow_flag = SUM_256_256(l_ret, l_tmp, &l_ret); + if (overflow_flag) { + //todo: change string to uint256_max after implementation + return log_it(L_ERROR, "Too big number '%s', max number is '%s'", a_256bit_num, "115792089237316195423570985008687907853269984665640564039457584007913129639935"), l_nul; + } if (l_ret.hi == 0 && l_ret.lo == 0) { return l_nul; } @@ -812,7 +843,11 @@ uint256_t dap_cvt_str_to_uint256(const char *a_256bit_num) return l_nul; } l_tmp.hi = l_mul << 64; - SUM_256_256(l_ret, l_tmp, &l_ret); + overflow_flag = SUM_256_256(l_ret, l_tmp, &l_ret); + if (overflow_flag) { + //todo: change string to uint256_max after implementation + return log_it(L_ERROR, "Too big number '%s', max number is '%s'", a_256bit_num, "115792089237316195423570985008687907853269984665640564039457584007913129639935"), l_nul; + } if (l_ret.hi == 0 && l_ret.lo == 0) { return l_nul; }