HIGH integer overflowchi

Integer Overflow in Chi

How Integer Overflow Manifests in Chi

Integer overflow in Chi manifests primarily through arithmetic operations on numeric types when values exceed their maximum representable range. In Chi's statically-typed system, this occurs most frequently with i32, u32, and i64 types during calculations involving user input, counters, or resource limits.

A common vulnerability pattern emerges in pagination logic where page sizes are multiplied by page numbers without bounds checking. Consider a Chi API endpoint that calculates record offsets:

fn get_records(page: i32, page_size: i32) -> Vec<Record> {
    let offset = page * page_size; // Integer overflow here if page=1M, page_size=1000
    db.query("SELECT * FROM records LIMIT ? OFFSET ?", page_size, offset)
}

When page=1,000,000 and page_size=1000, the multiplication 1,000,000 * 1000 = 1,000,000,000 exceeds i32's maximum value (2,147,483,647), causing wrap-around to a negative number. This produces unpredictable database queries and potential information disclosure.

Financial calculations in Chi applications are particularly susceptible. A shopping cart total calculation might overflow when summing item prices:

fn calculate_total(items: Vec<Item>) -> i32 {
    let mut total: i32 = 0;
    for item in items {
        total += item.price * item.quantity; // Overflow if total exceeds 2^31-1
    }
    total
}

With high-value items or large quantities, the total can wrap around, creating negative totals that bypass payment validation. Attackers can exploit this by adding items to push the total just below zero, potentially receiving products for free or triggering refund logic.

Loop counters in Chi can also overflow, especially in recursive operations or batch processing. A file processing endpoint might look like:

fn process_files(files: Vec<FileInfo>) -> Result<(), Error> {
    let mut processed_count: i32 = 0;
    for file in files {
        process_file(file)?;
        processed_count += 1; // Can overflow with large file sets
        if processed_count > 1000 { // Overflow bypasses this check
            break;
        }
    }
    Ok(())
}

With more than 2^31 files, processed_count wraps to negative, bypassing the break condition and potentially causing infinite processing or memory exhaustion.

Chi-Specific Detection

Detecting integer overflow in Chi requires both static analysis and runtime monitoring. Static analysis tools can identify risky arithmetic patterns, but Chi's compiler doesn't catch all overflow scenarios since it assumes well-behaved input.

middleBrick's scanner specifically targets integer overflow vulnerabilities in Chi APIs through black-box testing. The scanner sends boundary-value inputs to arithmetic operations, testing for wrap-around behavior. For pagination endpoints, middleBrick submits extremely large page numbers and sizes to trigger overflow conditions.

# Using middleBrick CLI to scan a Chi API
middlebrick scan https://api.example.com/records \
  --method POST \
  --payload '{"page": 2000000000, "page_size": 1000}' \
  --check overflow

The scanner monitors response patterns that indicate overflow: negative values in pagination parameters, unexpected database errors, or inconsistent totals. For financial endpoints, middleBrick tests with high-value items and quantities to identify wrap-around in price calculations.

Runtime detection in Chi applications can use checked arithmetic wrappers. Chi provides built-in overflow detection through the checked_* methods:

use std::num::Wrapping;

fn safe_multiply(a: i32, b: i32) -> Option<i32> {
    a.checked_mul(b) // Returns None on overflow instead of wrapping
}

fn safe_addition(total: i32, amount: i32) -> Result<i32, String> {
    match total.checked_add(amount) {
        Some(sum) => Ok(sum),
        None => Err("Integer overflow detected".to_string())
    }
}

middleBrick's continuous monitoring (Pro plan) can be configured to periodically test Chi APIs with overflow-inducing inputs, alerting developers when new vulnerabilities appear in production.

Chi-Specific Remediation

Chi provides several native approaches to prevent integer overflow. The most straightforward is using checked arithmetic operations that return Result or Option types instead of wrapping:

fn calculate_total(items: Vec<Item>) -> Result<i32, String> {
    let mut total: i32 = 0;
    for item in items {
        let item_total = item.price.checked_mul(item.quantity)
            .ok_or("Overflow in item calculation")?;
        total = total.checked_add(item_total)
            .ok_or("Overflow in total calculation")?;
    }
    Ok(total)
}

fn safe_pagination(page: i32, page_size: i32) -> Result<(i32, i32), String> {
    let offset = page.checked_mul(page_size)
        .ok_or("Page offset overflow")?;
    let limit = page_size.checked_add(1)
        .ok_or("Page size overflow")?;
    Ok((offset, limit))
}

For scenarios requiring larger ranges, Chi supports arbitrary-precision arithmetic through the bigint crate. This eliminates overflow entirely at the cost of performance:

use bigint::BigInt;

fn financial_calculation(items: Vec<Item>) -> BigInt {
    let mut total = BigInt::from(0);
    for item in items {
        let item_total = BigInt::from(item.price) * BigInt::from(item.quantity);
        total = total + item_total;
    }
    total
}

// For pagination with arbitrary limits
fn unbounded_pagination(page: i64, page_size: i64) -> (BigInt, BigInt) {
    let page = BigInt::from(page);
    let page_size = BigInt::from(page_size);
    let offset = page * page_size;
    let limit = page_size;
    (offset, limit)
}

Input validation is critical in Chi applications. Validate that numeric inputs fall within safe ranges before processing:

const MAX_PAGE_SIZE: i32 = 1000;
const MAX_PAGE_NUMBER: i32 = 1_000_000;

fn validate_pagination(page: i32, page_size: i32) -> Result<(), String> {
    if page < 0 || page > MAX_PAGE_NUMBER {
        return Err("Page number out of bounds");
    }
    if page_size <= 0 || page_size > MAX_PAGE_SIZE {
        return Err("Page size out of bounds");
    }
    Ok(())
}

fn get_records(page: i32, page_size: i32) -> Result<Vec<Record>, String> {
    validate_pagination(page, page_size)?;
    let (offset, limit) = safe_pagination(page, page_size)?;
    // Safe database query
    Ok(db.query("SELECT * FROM records LIMIT ? OFFSET ?", limit, offset))
}

For high-security applications, combine multiple defenses: checked arithmetic, input validation, and arbitrary-precision types for critical calculations. middleBrick's GitHub Action can enforce these patterns by failing builds when overflow-prone code is detected in your Chi codebase.

Frequently Asked Questions

Why doesn't Chi's compiler catch integer overflow by default?
Chi's compiler uses two's complement wrapping semantics for integer arithmetic by default, matching hardware behavior for performance. This design choice prioritizes speed over safety, assuming developers will handle overflow explicitly when needed. The -ftrapv flag enables overflow traps, but this isn't the default. middleBrick helps identify overflow vulnerabilities that the compiler won't catch.
What's the difference between <code>checked_*</code> and <code>overflowing_*</code> methods in Chi?
The checked_* methods return Option types, yielding None on overflow, which is safer for validation. The overflowing_* methods return a tuple of (result, boolean), where the boolean indicates overflow occurred. For security-critical code, checked_* is preferred as it forces explicit handling of the overflow case.