What do you call vsnprintf () safe?

I am migrating very old (> 10y) C code to modern Linux. I get segmentation errors in a specially created vsnprintf () shell (apparently, its task is to detect duplicate output lines and set them):

char* strVPrintf(const String fmt, va_list ap)
{
  /* Guess we need no more than 50 bytes. */
  int n, size = 50;
  char* p = (char*)memMalloc(size), q;

  while (1) {
    /* Try to print in the allocated space. */
    n = vsnprintf(p, size, fmt, ap);
    /* If that worked, return the string. */
    if (n > -1 && n < size) {
      break;
    }
    /* Else try again with more space. */
    if (n > -1)                /* glibc 2.1 */
      size = n + 1;            /* precisely what is needed */
    else                   /* glibc 2.0 */
      size *= 2;               /* twice the old size */
    p = memRealloc(p, size);
  }

  q =  strRegister(p);
  memFree(p);
  return q;
}

The author seems to have suggested that the standard function vsnprintf()returns the number of characters written and simply returns the counter value if it does not get enough space to format all the arguments. This means that you can simply guess the size of the buffer and increase it if necessary.

(Ubuntu 14.04, glibc 2.19) vnprintf . snprintf(), ? ?

+4
3

snprintf vsnprintf , SunOS 4 ( 20 ), - .

, , , va_list ap vsnprintf, , , reset on . gcc ( ).

:

n = vsnprintf(p, size, fmt, ap);

To:

va_list apc;
va_copy(apc, ap);
n = vsnprintf(p, size, fmt, apc);
va_end(apc);

, .

, , :

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

void
foo(const char *fmt, va_list ap)
{
#ifdef BAD
    vprintf(fmt, ap);
#else
    va_list apc;
    va_copy(apc, ap);
    vprintf(fmt, apc);
    va_end(apc);
#endif
    vprintf(fmt, ap);
}

void
bar(const char *fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    foo(fmt, ap);
    va_end(ap);
}

int
main(int argc, char **argv)
{
    bar("foo %s\n", "bar");
    return 0;
}

:

$ cc -o foo foo.c && ./foo
foo bar
foo bar
$ cc -DBAD -o foo foo.c && ./foo
foo bar
foo     
+7

, - , sprintf . : asprintf ( vasprintf ).

Prototype:

int vasprintf(char **strp, const char *fmt, va_list ap);

, :

String strVPrintf(const String fmt, va_list ap)
{
    char *ans;
    int n;
    n = vasprintf(&ans, fmt, ap);
    // do the checks
    return ans;
}

, , .

+2

, , man :


      , .       include < varargs.h > .

, , , va_list, , va_list, vsnprintf. , ( vsnprintf stdarg.h)

+2

All Articles