HACKERONE

curl: Stack Buffer Overflow in mprintf.c formatting function (fallback path)_H1:3493602

Description

### Summary
A stack-based buffer overflow exists in `mprintf.c` within the `out_double()` function. This vulnerability affects builds where `HAVE_SNPRINTF` is undefined, forcing the use of the legacy `sprintf` function.

The logic responsible for calculating the maximum safe precision (`maxprec`) for floating-point formatting fails to correctly handle negative numbers. Specifically, it does not properly account for the number of digits required by the integer portion of negative values. As a result, the buffer size calculation is incorrect, allowing a subsequent `sprintf` call to write more data than the fixed-size stack buffer can hold.


### Affected Component
- **File:** `lib/mprintf.c`
- **Function:** `out_double()`
- **Vulnerable Condition:** `HAVE_SNPRINTF` is not defined at compile time


### Technical Details
The function uses a local stack buffer (`work`) of size `BUFFSIZE` (326 bytes). To prevent overflow, the code attempts to estimate the number of digits required for the integer part of the floating-point value and reduce the allowable precision accordingly.

The relevant code is shown below (approx. line 675 in `master`):

```c
while(val >= 10.0) {
val /= 10;
maxprec--;
}
````

For negative values (e.g., `-1.0e100`), the condition `val >= 10.0` is false on entry, so the loop is skipped entirely. As a result, `maxprec` is not reduced, even though the integer portion of the formatted value will consume significant buffer space. The subsequent `sprintf` call writes the minus sign, the full integer portion, and the requested fractional precision, exceeding the 326-byte stack buffer.


## Steps To Reproduce

1. **Configure the Build**

Compile `libcurl` with `HAVE_SNPRINTF` undefined to force the fallback `sprintf` path. One way to simulate this is by modifying `lib/mprintf.c`:

```c
#if 0 /* Force fallback path for testing */
(snprintf)(work, BUFFSIZE, formatbuf, dnum);
#else
(sprintf)(work, formatbuf, dnum); /* Vulnerable path */
#endif
```

2. **Compile Reproduction Program**

Compile the following C program against the modified `libcurl` build:

```c
#include <stdio.h>
#include <curl/curl.h>
#include <string.h>

int main(void) {
// -1.0e100 requires ~102 characters for the integer part
// Precision .300 requires 300 characters for the fractional part
// Total output length ~402 characters
// Stack buffer size in mprintf.c is 326 bytes
double v = -1.0e100;

char *output = curl_maprintf("%.300f", v);

if (output) {
printf("Output length: %lu bytes\n",
(unsigned long)strlen(output));
curl_free(output);
}
return 0;
}
```

3. **Run the Program**

4. **Observe**

The output length exceeds the 326-byte buffer size. Depending on stack protections (stack canaries, ASLR), this results in a segmentation fault or stack smashing detection.


## Suggested Fix

Correct the integer digit calculation to account for negative values by operating on the absolute value (or equivalent logic):

```c
double absval = fabs(val);

while(absval >= 10.0) {
absval /= 10.0;
maxprec--;
}
```

Optionally, clamp `maxprec` to prevent underflow:

```c
if(maxprec < 0)
maxprec = 0;
```

## Impact

This vulnerability results in a classic stack-based buffer overflow.

* **Availability:** Denial of Service (application crash)
* **Security Impact:** In scenarios where the floating-point value and format string are influenced by attacker-controlled input, this issue could potentially be leveraged for further memory corruption, including control-flow manipulation.
* **Scope:** The vulnerable code path is part of the legacy fallback implementation and is not used in default modern curl builds. It primarily affects legacy Unix systems, embedded platforms, or custom builds where `snprintf` is unavailable or explicitly disabled.
Visit Original Source

Basic Information

ID H1:3493602
Published Jan 7, 2026 at 22:12
Modified Jan 8, 2026 at 09:36

💭 Join the Security Discussion

🔒 Your email address will not be published. Required fields are marked *

⚠️ Please be respectful and constructive in your comments. Security discussions should remain professional.