Weakness reference
CWE-1077

Floating Point Comparison with Incorrect Operator

This weakness occurs when code compares floating-point numbers for exact equality, ignoring the inherent imprecision of how computers represent decimal values…

01Summary

This weakness occurs when code compares floating-point numbers for exact equality, ignoring the inherent imprecision of how computers represent decimal values. Because floating-point arithmetic is approximate, two values that should be mathematically equal may differ by a tiny amount, causing equality checks to fail unexpectedly. In security-sensitive contexts—such as price validation, permission checks, or cryptographic operations—this can lead to bypasses or incorrect decisions.

02How It Happens

Floating-point numbers are stored in binary format with limited precision. Operations like division, multiplication, and addition accumulate small rounding errors. When code uses == or != to compare floats directly, it checks for bit-exact equality, not mathematical equivalence. A value computed through one sequence of operations may differ from the same value computed differently by a fraction of a unit in the last place (ULP), even though both represent the "same" number mathematically. Security checks that rely on exact equality—such as verifying a discount amount, checking a balance threshold, or validating a computed hash component—can be bypassed or triggered incorrectly.

03Real-World Impact

An attacker could exploit this to bypass price validation (e.g., making a payment appear to match a required amount when it doesn't), circumvent permission checks based on numeric thresholds, or trigger unintended behavior in financial calculations. In cryptographic or authentication contexts, floating-point comparisons can lead to signature verification failures or acceptance of invalid credentials. The impact ranges from minor logic errors to serious security bypasses, depending on what decision the comparison guards.

04Vulnerable & Fixed Patterns

Vulnerable pattern
def validate_discount(original_price, discount_rate, final_price):
    calculated_price = original_price * (1 - discount_rate)
    if calculated_price == final_price:
        return True
    return False

# Due to floating-point rounding, this may fail even when prices should match
result = validate_discount(99.99, 0.1, 89.991)

Why it's vulnerable:
The multiplication and subtraction introduce rounding errors. calculated_price may be 89.99099999999999 while final_price is 89.991, causing the equality check to fail despite representing the same intended value.

Fixed pattern
def validate_discount(original_price, discount_rate, final_price):
    calculated_price = original_price * (1 - discount_rate)
    tolerance = 1e-9
    if abs(calculated_price - final_price) < tolerance:
        return True
    return False

result = validate_discount(99.99, 0.1, 89.991)
Vulnerable pattern
function validate_balance($account_balance, $required_amount) {
    if ($account_balance == $required_amount) {
        return true;
    }
    return false;
}

$balance = 100.1 - 0.1;  // May be 99.99999999999999
$required = 100.0;
validate_balance($balance, $required);

Why it's vulnerable:
Floating-point arithmetic produces $balance as something slightly less than 100.0 due to rounding, so the equality check fails even though the values are intended to be equal.

Fixed pattern
function validate_balance($account_balance, $required_amount) {
    $tolerance = 1e-9;
    if (abs($account_balance - $required_amount) < $tolerance) {
        return true;
    }
    return false;
}

$balance = 100.1 - 0.1;
$required = 100.0;
validate_balance($balance, $required);

05Prevention Checklist

Use epsilon-based comparison:
Always compare floats by checking if the absolute difference is smaller than a small tolerance value (epsilon), not by testing equality.
Avoid floats for currency and exact values:
Use integer arithmetic (e.g., store prices in cents) or a decimal library designed for exact arithmetic instead of binary floating-point.
Document precision requirements:
Clearly specify the acceptable tolerance for any floating-point comparison in security-sensitive code.
Test edge cases:
Include test cases that verify comparisons work correctly with values produced by arithmetic operations, not just hardcoded literals.
Use appropriate data types:
For financial or cryptographic calculations, prefer Decimal (Python) or bcmath/GMP (PHP) over native floats.
Review all security-relevant comparisons:
Audit code that makes access-control, validation, or authentication decisions based on numeric comparisons.

06Signs You May Already Be Affected

Look for unexpected validation failures or bypasses in code that checks numeric thresholds, prices, or balances. If users report that transactions fail to process despite correct amounts, or if security checks seem to trigger inconsistently, floating-point comparison issues may be involved. Review logs for patterns where similar operations succeed or fail unpredictably.