]> granicus.if.org Git - json-c/commit
vasprintf(): avoid out of memory accesses
authorTobias Stoeckmann <tobias@stoeckmann.org>
Thu, 24 Feb 2022 20:35:44 +0000 (21:35 +0100)
committerTobias Stoeckmann <tobias@stoeckmann.org>
Thu, 24 Feb 2022 22:06:57 +0000 (23:06 +0100)
commit5c722572200e998736317090281f5dddc13bc311
tree606530a304e07f1507c0221cf233c945bc6486f1
parent66cce0a1d7ec68301421591dec6b88c4a43c7cde
vasprintf(): avoid out of memory accesses

Systems without vasprintf fall back to implementation in header file
vasprintf_compat.h. This version could run into heap overflow issues
with very long arguments or formats provoking a lot of output.

The vsnprintf function returns a negative value if more than INT_MAX
characters would be written since its int return type could not
handle this (and %n couldn't handle it either).

Before testing for a possible error value the additional char for
\0 is already added. A -1 error code would not be detected.

Increment only after implicitly casting to an unsigned value to avoid
signed integer overflow if INT_MAX has been returned.

Use va_copy to duplicate the original ap argument for multiple uses
on non-WIN32 systems. At least with glibc the test suite would fail
because the arguments are not reset after leaving the vsnprintf call.

Removed support for apparently very old glibc versions which do not
comply with vsnprintf standard descriptions. It breaks support for
modern ones which are not forced to return -1 in case of error. The
standard specifies merely "a negative value".

How to reproduce:

- Use a system without vasprintf
- Alternatively remove -D_GNU_SOURCE from CMakeLists.txt
- Compile and run:

  #include "json.h"
  int main(void) {
    struct printbuf *pb = printbuf_new();
    sprintbuf(pb, "prefix %2147483647s", "*");
    printbuf_free(pb);
    return 0;
  }
vasprintf_compat.h