CWE-1339: Insufficient Precision or Accuracy of a Real Number

Description

The product processes a real number with an implementation in which the number's representation does not preserve required accuracy and precision in its fractional part, causing an incorrect result.

Submission Date :

July 8, 2021, midnight

Modification Date :

2023-06-29 00:00:00+00:00

Organization :

MITRE
Extended Description

When a security decision or calculation requires highly precise, accurate numbers such as financial calculations or prices, then small variations in the number could be exploited by an attacker.

There are multiple ways to store the fractional part of a real number in a computer. In all of these cases, there is a limit to the accuracy of recording a fraction. If the fraction can be represented in a fixed number of digits (binary or decimal), there might not be enough digits assigned to represent the number. In other cases the number cannot be represented in a fixed number of digits due to repeating in decimal or binary notation (e.g. 0.333333...) or due to a transcendental number such as Π or √2. Rounding of numbers can lead to situations where the computer results do not adequately match the result of sufficiently accurate math.

Example Vulnerable Codes

Example - 1

Muller's Recurrence is a series that is supposed to converge to the number 5. When running this series with the following code, different implementations of real numbers fail at specific iterations:



108.0 - ((815.0 - 1500.0 / z) / y);


x.push(rec_float(x[number - 1], x[number - 2]));
let mut x: Vec<f64> = vec![4.0, 4.25];(2..turns + 1).for_each(|number| {});x[turns]
fn rec_float(y: f64, z: f64) -> f64 {}fn float_calc(turns: usize) -> f64 {}

The chart below shows values for different data structures in the rust language when Muller's recurrence is executed to 80 iterations. The data structure f64 is a 64 bit float. The data structures IF are fixed representations 128 bits in length that use the first number as the size of the integer and the second size as the size of the fraction (e.g. I16F112 uses 16 bits for the integer and 112 bits for the fraction). The data structure of Ratio comes in three different implementations: i32 uses a ratio of 32 bit signed integers, i64 uses a ratio of 64 bit signed integers and BigInt uses a ratio of signed integer with up to 2^32 digits of base 256. Notice how even with 112 bits of fractions or ratios of 64bit unsigned integers, this math still does not converge to an expected value of 5.




- ((BigRational::from_integer(BigInt::from(815))- BigRational::from_integer(BigInt::from(1500)) / z)/ y)BigRational::from_integer(BigInt::from(108))


x.push(rec_big(x[number - 1].clone(), x[number - 2].clone()));
let mut x: Vec<BigRational> = vec![BigRational::from_float(4.0).unwrap(), BigRational::from_float(4.25).unwrap(),];(2..turns + 1).for_each(|number| {});x[turns].clone()
Use num_rational::BigRational;fn rec_big(y: BigRational, z: BigRational) -> BigRational{}fn big_calc(turns: usize) -> BigRational {}

Example - 2

On February 25, 1991, during the eve of the of an Iraqi invasion of Saudi Arabia, a Scud missile fired from Iraqi positions hit a US Army barracks in Dhahran, Saudi Arabia. It miscalculated time and killed 28 people [REF-1190].

Example - 3

Sleipner A, an offshore drilling platform in the North Sea, was incorrectly constructed with an underestimate of 50% of strength in a critical cluster of buoyancy cells needed for construction. This led to a leak in buoyancy cells during lowering, causing a seismic event of 3.0 on the Richter Scale and about $700M loss [REF-1281].

Related Weaknesses

This table shows the weaknesses and high level categories that are related to this weakness. These relationships are defined to give an overview of the different insight to similar items that may exist at higher and lower levels of abstraction.

Visit http://cwe.mitre.org/ for more details.