What Is an Integer Overflow Vulnerability?
An integer overflow vulnerability wraps a size calculation to a tiny number, so code writes past its buffer. Here is how that becomes code execution.
An integer overflow vulnerability happens when a program calculates a number too large for the variable that stores it, and the value silently wraps around to a small or negative number. On its own that is just a wrong answer. It becomes a security flaw when the wrapped number is then used to size a memory buffer or check a boundary, because the program writes more data than it reserved. That corrupted memory is how a math bug turns into remote code execution.
What is an integer overflow?
An integer overflow is what happens when arithmetic produces a result outside the range a fixed-size integer type can hold. Instead of failing, the value wraps around, so a very large number becomes a very small one.
Computers store integers in a fixed number of bits. An unsigned 32-bit integer holds values from 0 to 4,294,967,295. Add 1 to the maximum and, in languages like C, you get 0. Signed integers wrap from the largest positive value to the most negative one. Nothing crashes at that moment. The program carries on with a number that no longer means what the developer intended.
unsigned 32-bit maximum: 4,294,967,295
add 1: 0
count x size (wrapped): small value, buffer far too small
How does an integer overflow lead to code execution?
The overflow itself does nothing dangerous. The damage comes when the wrapped value decides how much memory to allocate, or whether an index is in bounds, and later code writes the real, much larger amount of data into the undersized space.
The usual sequence looks like this:
- The program computes a size, often by multiplying a count by an element size or adding lengths together.
- The calculation wraps, so the size comes out small.
- The program allocates a buffer of that small size.
- A later loop or copy uses the original, unwrapped count and writes past the end of the buffer.
- The overflow corrupts adjacent memory, such as other data structures, function pointers or allocator metadata.
Step 5 is a heap or stack buffer overflow, and that is the point where an attacker who controls the input can sometimes steer the program into running their code. This is why integer overflows carry the weakness ID CWE-190 and often appear next to CWE-787 (out-of-bounds write) in advisories.
A real integer overflow vulnerability: GitLab CVE-2026-97229
In October 2026 GitLab patched CVE-2026-97229, a CVSS 10.0 flaw that CISA later added to its Known Exploited Vulnerabilities catalog. GitLab compiles regular expressions that users put in CI/CD configuration. The Ruby core team traced the bug to an integer overflow in the size of a compiled pattern inside Onigmo, Ruby's regular expression engine. A crafted pattern made the size calculation wrap, memory was corrupted during compilation, and GitLab found the result could be turned into code execution on the server.
The example shows two common traits of this bug class. First, the overflow sat deep in a library (Onigmo) that the application (GitLab) trusted. Second, the input that triggered it was not obviously dangerous: a regular expression in a configuration file. We look at that second point in why untrusted regex patterns are a code execution risk.
Why are integer overflows so hard to spot?
Integer overflows are hard to spot because the vulnerable line usually looks like ordinary arithmetic, and the failure only appears with extreme input values that normal testing never uses.
A reviewer reading size = count * width sees correct logic. The bug only exists when count and width are large enough together to exceed the type's range, and the code that misuses the result is often in a different function. Tests built around realistic data never reach those values. Fuzzing tends to find these bugs because it deliberately feeds boundary values.
Which languages are affected?
Languages differ in what happens on overflow:
- C and C++: unsigned integers wrap silently. Signed overflow is undefined behavior, which compilers may optimize in surprising ways. Most exploitable integer overflows live here.
- Rust: overflow panics in debug builds and wraps in release builds unless the code uses checked or saturating arithmetic. Memory safety rules still prevent most out-of-bounds writes, so a wrapped value is less likely to become code execution.
- Java and C#: integers wrap, but array bounds are checked at runtime, so the usual outcome is an exception or a logic error rather than memory corruption.
- Python and Ruby: their native integers grow as needed and do not overflow. Their interpreters and native extensions are written in C, though, which is exactly where the Onigmo bug lived.
The lesson for operators: a memory-safe application language does not make the stack underneath it memory safe. Ruby code cannot overflow an integer, but the C engine that compiles Ruby's regular expressions could.
How do developers prevent integer overflows?
Developers prevent integer overflows by checking arithmetic before using its result for memory or bounds decisions, and by using compiler and library features that make overflow loud instead of silent.
Practical controls include:
- Validate inputs against sane maximums before doing size arithmetic.
- Use checked arithmetic helpers that report overflow, and refuse to allocate when they do.
- Prefer allocation functions that take a count and an element size separately and check the product.
- Enable compiler warnings and sanitizers (such as undefined behavior and address sanitizers) in test builds.
- Fuzz any parser that accepts external input, especially parsers for formats, compressed data and pattern languages.
What should operators do about integer overflow CVEs?
Operators cannot fix the arithmetic themselves, so their job is to know where the vulnerable component lives and patch it everywhere. An integer overflow in a shared library usually affects every product that bundles that library.
For the GitLab case that meant two upgrades: GitLab itself, and any separate Ruby runtime used by other applications. Our guide on how to fix the Ruby Onigmo regexp bugs covers the second part. When an advisory lists CWE-190 next to a high CVSS score and network reachability, treat it as a likely code execution bug, whatever the headline says.