mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
Fix undefined behavior code (#464)
* Fix UB in arithmetics * Fix misaligned allocations in validator sessions * Fix integer overflow in bigint.hpp * Fix potential UB Co-authored-by: SpyCheese <mikle98@yandex.ru>
This commit is contained in:
parent
440d06962a
commit
9c6787d2ff
8 changed files with 86 additions and 71 deletions
|
@ -176,6 +176,7 @@ class AnyIntView {
|
|||
public:
|
||||
enum { word_bits = Tr::word_bits, word_shift = Tr::word_shift };
|
||||
typedef typename Tr::word_t word_t;
|
||||
typedef typename Tr::uword_t uword_t;
|
||||
int& n_;
|
||||
PropagateConstSpan<word_t> digits;
|
||||
|
||||
|
@ -320,7 +321,7 @@ class BigIntG {
|
|||
digits[0] = x;
|
||||
normalize_bool();
|
||||
} else {
|
||||
digits[0] = ((x + Tr::Half) & (Tr::Base - 1)) - Tr::Half;
|
||||
digits[0] = ((x ^ Tr::Half) & (Tr::Base - 1)) - Tr::Half;
|
||||
digits[n++] = (x >> Tr::word_shift) + (digits[0] < 0);
|
||||
}
|
||||
}
|
||||
|
@ -675,7 +676,7 @@ class BigIntG {
|
|||
return n > 0 && !(digits[0] & 1);
|
||||
}
|
||||
word_t mod_pow2_short(int pow) const {
|
||||
return n > 0 ? digits[0] & ((1 << pow) - 1) : 0;
|
||||
return n > 0 ? digits[0] & ((1ULL << pow) - 1) : 0;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -764,7 +765,7 @@ bool AnyIntView<Tr>::add_pow2_any(int exponent, int factor) {
|
|||
while (size() <= k) {
|
||||
digits[inc_size()] = 0;
|
||||
}
|
||||
digits[k] += ((word_t)factor << dm.rem);
|
||||
digits[k] += factor * ((word_t)1 << dm.rem);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -969,7 +970,7 @@ bool AnyIntView<Tr>::add_mul_any(const AnyIntView<Tr>& yp, const AnyIntView<Tr>&
|
|||
if (hi && hi != -1) {
|
||||
return invalidate_bool();
|
||||
}
|
||||
digits[size() - 1] += (hi << word_shift);
|
||||
digits[size() - 1] += ((uword_t)hi << word_shift);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1014,7 +1015,7 @@ int AnyIntView<Tr>::sgn_un_any() const {
|
|||
}
|
||||
int i = size() - 2;
|
||||
do {
|
||||
v <<= word_shift;
|
||||
v *= Tr::Base;
|
||||
word_t w = digits[i];
|
||||
if (w >= -v + Tr::MaxDenorm) {
|
||||
return 1;
|
||||
|
@ -1059,7 +1060,7 @@ typename Tr::word_t AnyIntView<Tr>::to_long_any() const {
|
|||
} else if (size() == 1) {
|
||||
return digits[0];
|
||||
} else {
|
||||
word_t v = digits[0] + (digits[1] << word_shift); // approximation mod 2^64
|
||||
word_t v = (uword_t)digits[0] + ((uword_t)digits[1] << word_shift); // approximation mod 2^64
|
||||
word_t w = (v & (Tr::Base - 1)) - digits[0];
|
||||
w >>= word_shift;
|
||||
w += (v >> word_shift); // excess of approximation divided by Tr::Base
|
||||
|
@ -1120,7 +1121,7 @@ int AnyIntView<Tr>::cmp_un_any(const AnyIntView<Tr>& yp) const {
|
|||
return -1;
|
||||
}
|
||||
while (xn > yn) {
|
||||
v <<= word_shift;
|
||||
v *= Tr::Base;
|
||||
word_t w = T::eval(digits[--xn]);
|
||||
if (w >= -v + Tr::MaxDenorm) {
|
||||
return 1;
|
||||
|
@ -1137,7 +1138,7 @@ int AnyIntView<Tr>::cmp_un_any(const AnyIntView<Tr>& yp) const {
|
|||
return -1;
|
||||
}
|
||||
while (yn > xn) {
|
||||
v <<= word_shift;
|
||||
v *= Tr::Base;
|
||||
word_t w = yp.digits[--yn];
|
||||
if (w <= v - Tr::MaxDenorm) {
|
||||
return 1;
|
||||
|
@ -1150,7 +1151,7 @@ int AnyIntView<Tr>::cmp_un_any(const AnyIntView<Tr>& yp) const {
|
|||
v = 0;
|
||||
}
|
||||
while (--xn >= 0) {
|
||||
v <<= word_shift;
|
||||
v *= Tr::Base;
|
||||
word_t w = T::eval(digits[xn]) - yp.digits[xn];
|
||||
if (w >= -v + Tr::MaxDenorm) {
|
||||
return 1;
|
||||
|
@ -1197,7 +1198,7 @@ int AnyIntView<Tr>::divmod_tiny_any(int y) {
|
|||
}
|
||||
int rem = 0;
|
||||
for (int i = size() - 1; i >= 0; i--) {
|
||||
auto divmod = std::div(digits[i] + ((word_t)rem << word_shift), (word_t)y);
|
||||
auto divmod = std::div(digits[i] + ((uword_t)rem << word_shift), (word_t)y);
|
||||
digits[i] = divmod.quot;
|
||||
rem = (int)divmod.rem;
|
||||
if ((rem ^ y) < 0 && rem) {
|
||||
|
@ -1267,7 +1268,7 @@ bool AnyIntView<Tr>::mul_add_short_any(word_t y, word_t z) {
|
|||
z += (digits[size() - 1] >> word_shift);
|
||||
digits[size() - 1] &= Tr::Base - 1;
|
||||
if (!z || z == -1) {
|
||||
digits[size() - 1] += (z << word_shift);
|
||||
digits[size() - 1] += ((uword_t)z << word_shift);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -1338,7 +1339,7 @@ bool AnyIntView<Tr>::mod_div_any(const AnyIntView<Tr>& yp, AnyIntView<Tr>& quot,
|
|||
while (--i >= 0) {
|
||||
Tr::sub_mul(&digits[k + i + 1], &digits[k + i], q, yp.digits[i]);
|
||||
}
|
||||
digits[size() - 1] += (hi << word_shift);
|
||||
digits[size() - 1] += ((uword_t)hi << word_shift);
|
||||
}
|
||||
} else {
|
||||
quot.set_size(1);
|
||||
|
@ -1351,7 +1352,7 @@ bool AnyIntView<Tr>::mod_div_any(const AnyIntView<Tr>& yp, AnyIntView<Tr>& quot,
|
|||
Tr::sub_mul(&digits[k + i + 1], &digits[k + i], q, yp.digits[i]);
|
||||
}
|
||||
dec_size();
|
||||
digits[size() - 1] += (digits[size()] << word_shift);
|
||||
digits[size() - 1] += ((uword_t)digits[size()] << word_shift);
|
||||
}
|
||||
if (size() >= yp.size() - 1) {
|
||||
assert(size() <= yp.size());
|
||||
|
@ -1455,7 +1456,7 @@ bool AnyIntView<Tr>::mod_pow2_any(int exponent) {
|
|||
dec_size();
|
||||
q += word_shift;
|
||||
}
|
||||
word_t pow = ((word_t)1 << q);
|
||||
uword_t pow = ((uword_t)1 << q);
|
||||
word_t v = digits[size() - 1] & (pow - 1);
|
||||
if (!v) {
|
||||
int k = size() - 1;
|
||||
|
@ -1485,7 +1486,7 @@ bool AnyIntView<Tr>::mod_pow2_any(int exponent) {
|
|||
return true;
|
||||
} else if (v >= Tr::Half && size() < max_size()) {
|
||||
word_t w = (((v >> (word_shift - 1)) + 1) >> 1);
|
||||
digits[size() - 1] = v - (w << word_shift);
|
||||
digits[size() - 1] = (uword_t)v - ((uword_t)w << word_shift);
|
||||
digits[inc_size()] = w;
|
||||
return true;
|
||||
} else {
|
||||
|
@ -1623,7 +1624,7 @@ bool AnyIntView<Tr>::lshift_any(int exponent) {
|
|||
} else if (v != -1) {
|
||||
return invalidate_bool();
|
||||
} else {
|
||||
digits[size() - 1] += (v << word_shift);
|
||||
digits[size() - 1] += ((uword_t)v << word_shift);
|
||||
}
|
||||
}
|
||||
if (q) {
|
||||
|
@ -1750,7 +1751,7 @@ int AnyIntView<Tr>::bit_size_any(bool sgnd) const {
|
|||
int k = size() - 1;
|
||||
word_t q = digits[k];
|
||||
if (k > 0 && q < Tr::MaxDenorm / 2) {
|
||||
q <<= word_shift;
|
||||
q *= Tr::Base;
|
||||
q += digits[--k];
|
||||
}
|
||||
if (!k) {
|
||||
|
@ -1766,7 +1767,7 @@ int AnyIntView<Tr>::bit_size_any(bool sgnd) const {
|
|||
} else if (q <= -Tr::MaxDenorm / 2) {
|
||||
return s;
|
||||
}
|
||||
q <<= word_shift;
|
||||
q *= Tr::Base;
|
||||
q += digits[--k];
|
||||
}
|
||||
return q >= 0 ? s + 1 : s;
|
||||
|
@ -1774,7 +1775,7 @@ int AnyIntView<Tr>::bit_size_any(bool sgnd) const {
|
|||
int k = size() - 1;
|
||||
word_t q = digits[k];
|
||||
if (k > 0 && q > -Tr::MaxDenorm / 2) {
|
||||
q <<= word_shift;
|
||||
q *= Tr::Base;
|
||||
q += digits[--k];
|
||||
}
|
||||
if (!k) {
|
||||
|
@ -1790,7 +1791,7 @@ int AnyIntView<Tr>::bit_size_any(bool sgnd) const {
|
|||
} else if (q <= -Tr::MaxDenorm / 2) {
|
||||
return s + 1;
|
||||
}
|
||||
q <<= word_shift;
|
||||
q *= Tr::Base;
|
||||
q += digits[--k];
|
||||
}
|
||||
return q >= 0 ? s : s + 1;
|
||||
|
@ -1817,7 +1818,7 @@ bool AnyIntView<Tr>::export_bytes_any(unsigned char* buff, std::size_t buff_size
|
|||
for (int i = 0; i < size(); i++) {
|
||||
if ((word_shift & 7) && word_shift + 8 >= word_bits && k >= word_bits - word_shift - 1) {
|
||||
int k1 = 8 - k;
|
||||
v += (digits[i] << k) & 0xff;
|
||||
v += ((uword_t)digits[i] << k) & 0xff;
|
||||
if (ptr > buff) {
|
||||
*--ptr = (unsigned char)(v & 0xff);
|
||||
} else if ((unsigned char)(v & 0xff) != s) {
|
||||
|
@ -1827,7 +1828,7 @@ bool AnyIntView<Tr>::export_bytes_any(unsigned char* buff, std::size_t buff_size
|
|||
v += (digits[i] >> k1);
|
||||
k += word_shift - 8;
|
||||
} else {
|
||||
v += (digits[i] << k);
|
||||
v += ((uword_t)digits[i] << k);
|
||||
k += word_shift;
|
||||
}
|
||||
while (k >= 8) {
|
||||
|
@ -1868,7 +1869,7 @@ bool AnyIntView<Tr>::export_bytes_lsb_any(unsigned char* buff, std::size_t buff_
|
|||
for (int i = 0; i < size(); i++) {
|
||||
if ((word_shift & 7) && word_shift + 8 >= word_bits && k >= word_bits - word_shift - 1) {
|
||||
int k1 = 8 - k;
|
||||
v += (digits[i] << k) & 0xff;
|
||||
v += ((uword_t)digits[i] << k) & 0xff;
|
||||
if (buff < end) {
|
||||
*buff++ = (unsigned char)(v & 0xff);
|
||||
} else if ((unsigned char)(v & 0xff) != s) {
|
||||
|
@ -1878,7 +1879,7 @@ bool AnyIntView<Tr>::export_bytes_lsb_any(unsigned char* buff, std::size_t buff_
|
|||
v += (digits[i] >> k1);
|
||||
k += word_shift - 8;
|
||||
} else {
|
||||
v += (digits[i] << k);
|
||||
v += ((uword_t)digits[i] << k);
|
||||
k += word_shift;
|
||||
}
|
||||
while (k >= 8) {
|
||||
|
@ -1922,7 +1923,7 @@ bool AnyIntView<Tr>::export_bits_any(unsigned char* buff, int offs, unsigned bit
|
|||
return false;
|
||||
}
|
||||
}
|
||||
td::bitstring::bits_store_long_top(buff, offs, v << (64 - bits), bits);
|
||||
td::bitstring::bits_store_long_top(buff, offs, (unsigned long long)v << (64 - bits), bits);
|
||||
} else {
|
||||
if (!sgnd && v < 0) {
|
||||
return false;
|
||||
|
@ -1945,7 +1946,7 @@ bool AnyIntView<Tr>::export_bits_any(unsigned char* buff, int offs, unsigned bit
|
|||
for (int i = 0; i < size(); i++) {
|
||||
if (word_shift + 8 >= word_bits && k >= word_bits - word_shift - 1) {
|
||||
int k1 = 8 - k;
|
||||
v += (digits[i] << k) & 0xff;
|
||||
v += ((uword_t)digits[i] << k) & 0xff;
|
||||
if (ptr > buff) {
|
||||
if (--ptr > buff) {
|
||||
*ptr = (unsigned char)(v & 0xff);
|
||||
|
@ -1963,7 +1964,7 @@ bool AnyIntView<Tr>::export_bits_any(unsigned char* buff, int offs, unsigned bit
|
|||
v += (digits[i] >> k1);
|
||||
k += word_shift - 8;
|
||||
} else {
|
||||
v += (digits[i] << k);
|
||||
v += ((uword_t)digits[i] << k);
|
||||
k += word_shift;
|
||||
}
|
||||
while (k >= 8) {
|
||||
|
@ -2028,7 +2029,7 @@ bool AnyIntView<Tr>::import_bytes_any(const unsigned char* buff, std::size_t buf
|
|||
return invalidate_bool();
|
||||
}
|
||||
}
|
||||
v |= (((word_t) * --ptr) << k);
|
||||
v |= (((uword_t) * --ptr) << k);
|
||||
k += 8;
|
||||
}
|
||||
if (s) {
|
||||
|
@ -2043,7 +2044,9 @@ bool AnyIntView<Tr>::import_bits_any(const unsigned char* buff, int offs, unsign
|
|||
if (bits < word_shift) {
|
||||
set_size(1);
|
||||
unsigned long long val = td::bitstring::bits_load_long_top(buff, offs, bits);
|
||||
if (sgnd) {
|
||||
if (bits == 0) {
|
||||
digits[0] = 0;
|
||||
} else if (sgnd) {
|
||||
digits[0] = ((long long)val >> (64 - bits));
|
||||
} else {
|
||||
digits[0] = (val >> (64 - bits));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue