Skip to content

fix Integer Overflow via Improper Cast in Valve's GameNetworkingSockets #372

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

odaysec
Copy link

@odaysec odaysec commented Apr 7, 2025

an integer overflow caused by performing a multiplication between two unsigned 32-bit integers and then casting the result to a larger data type (size_t) after the multiplication. This cast does not prevent the overflow, as the multiplication itself is already performed using the smaller type. If the multiplication result exceeds the maximum value representable by a 32-bit unsigned integer (i.e., 4,294,967,295), the result wraps around, producing a significantly smaller and incorrect value.

This can lead to serious memory allocation issues such as buffer overflows, heap corruption, and potentially remote code execution in certain scenarios. The vulnerability is classified under multiple Common Weakness Enumerations (CWEs), including CWE-190 (Integer Overflow), CWE-681 (Incorrect Conversion), and CWE-192 (Integer Coercion).

m_pMemory = PvAlloc( m_nAllocationCount * m_unSizeOfElements );

This rule finds code that converts the result of an integer multiplication to a larger type. Since the conversion applies after the multiplication, arithmetic overflow may still occur. The rule flags every multiplication of two non-constant integer expressions that is (explicitly or implicitly) converted to a larger integer type. The conversion is an indication that the expression would produce a result that would be too large to fit in the smaller integer type.

Vulnerable POC

The vulnerability is located in the following line within src/tier1/memory.cpp:

pMemory = Pvalloc(_allocationCount * m_uiSizeOfElements);

Here, both _allocationCount and m_uiSizeOfElements are declared as unsigned int (32-bit). When these two values are multiplied, the operation is carried out in 32-bit space, and the result is subject to overflow. Even though the result is stored in a size_t variable, the overflow has already occurred.

#include <iostream>
#include <cstdlib>

int main() {
    unsigned int count = 3000000000;   // large value
    unsigned int size = 4;             // 4-byte element size

    size_t actual = count * size;      // Overflow happens here

    std::cout << "Computed allocation size: " << actual << std::endl;

    void* ptr = malloc(actual);        // Pvalloc behavior
    if (!ptr) {
        std::cerr << "Memory allocation failed!" << std::endl;
    } else {
        std::cout << "Memory allocation succeeded!" << std::endl;
        free(ptr);
    }

    return 0;
}

Exploitation Potential

If this vulnerable allocation routine is used in scenarios where the allocation size is calculated based on external or user-controlled input, this bug can be exploited. An attacker can manipulate the size or count values to trigger a miscalculation. Since the application may believe a large buffer has been allocated (but in reality a small one has), subsequent writes to the allocated memory can overflow the buffer boundaries.

This can result in:

  • Heap memory corruption
  • Application crashes (DoS)
  • Potential remote code execution depending on the platform and allocator behavior

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant