HexBrain

curl · Report #3493602

Stack Buffer Overflow in mprintf.c formatting function (fallback path)

Informativestatus
highseverity
8upvotes
8 Jan 2026disclosed

How it was found

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):

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:

    #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:

    #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):

double absval = fabs(val);

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

Optionally, clamp maxprec to prevent underflow:

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.

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original