Skip to content

Use of snprintf and vsnprintf in Curl #3296

@thoger

Description

@thoger

The curl code base use snprintf or vsnprintf functions on multiple places. However - just like for all printf family functions - it uses its own implementation of those functions - curl_msnprintf and curl_mvsnprintf - which is achieved via macro definitions in curl_printf.h:

https://github.com/curl/curl/blob/curl-7_62_0/lib/curl_printf.h

However, there is a notable difference in what curl_m*snprintf functions return compared to what's defined for *snprintf in POSIX or C99 for the case when destination buffer is too small and the output is truncated:

  • curl functions return the number of characters written, which is also documented in https://curl.haxx.se/libcurl/c/curl_mprintf.html
  • POSIX requires the number of characters that should have been written if the destination buffer was sufficiently large

Looking at few cases where snprintf return value is not ignored, the curl code expects and relies on the curl implementation return values. There are often no checks to ensure that the return value does not exceed destination buffer size, and the value is directly used to increment the pointer that is used for subsequent writes, or decrement free space counter. That could lead to out-of-bounds buffer access and integer underflow if POSIX snprintf was used instead. An example of such code pattern can be found in e.g. curl_version():

https://github.com/curl/curl/blob/curl-7_62_0/lib/version.c#L129-L131

This can be a problem if *snprintf implementation used by curl is to be changed in the future, or if anyone tries to make curl use printf functions from their system C library instead of curl implementations.

This can also cause confusion to folks from outside of the Curl project who review or contribute to the code of the project.

The explicit use of curl_m*snprintf functions should be considered for places where non-standard return values are expected.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions