1
0
Fork 0
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:
EmelyanenkoK 2022-09-19 17:31:54 +03:00 committed by GitHub
parent 440d06962a
commit 9c6787d2ff
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 86 additions and 71 deletions

View file

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