Use big integer arithmetic to avoid multiplication overflow

This commit is contained in:
Konstantin Knizhnik
2022-03-31 12:53:41 +03:00
parent a31bc88e46
commit 2c94775ca8
3 changed files with 25 additions and 2 deletions

14
Cargo.lock generated
View File

@@ -1422,6 +1422,17 @@ dependencies = [
"num-traits",
]
[[package]]
name = "num-bigint"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-integer"
version = "0.1.44"
@@ -1522,6 +1533,7 @@ dependencies = [
"lazy_static",
"log",
"nix",
"num-bigint 0.4.3",
"num-traits",
"once_cell",
"postgres 0.19.1 (git+https://github.com/zenithdb/rust-postgres.git?rev=2949d98df52587d562986aad155dd4e889e408b7)",
@@ -2384,7 +2396,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "692ca13de57ce0613a363c8c2f1de925adebc81b04c923ac60c5488bb44abe4b"
dependencies = [
"chrono",
"num-bigint",
"num-bigint 0.2.6",
"num-traits",
]

View File

@@ -46,6 +46,7 @@ crossbeam-utils = "0.8.5"
fail = "0.5.0"
rstar = "0.9.2"
num-traits = "0.2.14"
num-bigint = "0.4.3"
rust-s3 = { version = "0.28", default-features = false, features = ["no-verify-ssl", "tokio-rustls-tls"] }
async-compression = {version = "0.3", features = ["zstd", "tokio"]}

View File

@@ -16,6 +16,8 @@ use crate::layered_repository::InMemoryLayer;
use crate::repository::Key;
use anyhow::Result;
use lazy_static::lazy_static;
use num_bigint::BigInt;
use num_traits::cast::ToPrimitive;
use num_traits::identities::{One, Zero};
use num_traits::{Bounded, Num, Signed};
use rstar::{RTree, RTreeObject, AABB};
@@ -134,7 +136,15 @@ impl Sub for IntKey {
impl Mul for IntKey {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
IntKey(self.0.wrapping_mul(rhs.0))
// Use big integer arithmetic to avoid overflow.
// We have to cacluate sqrt of the result to be able to store result of operation as i128.
// As far as multiplication is used by R-Tree to calculate area and distance, it should not be a problem.
IntKey(
(BigInt::from(self.0) * BigInt::from(rhs.0))
.sqrt()
.to_i128()
.unwrap(),
)
}
}