ccross-platformbuffer-overflowbuffer-overrun

How can I overcome inconsistent behaviour of snprintf in different UNIX-like operating systems?


Per man pages, snprintf is returning number of bytes written from glibc version 2.2 onwards. But on lower versions of libc2.2 and HP-UX, it returns a positive integer, which could lead to a buffer overflow.

How can one overcome this and write portable code?

Edit : For want of more clarity

This code is working perfectly in lib 2.3

    if ( snprintf( cmd, cmdLen + 1, ". %s%s", myVar1, myVar2 )  != cmdLen )
    {
        fprintf( stderr, "\nError: Unable to  copy bmake command!!!");
        returnCode = ERR_COPY_FILENAME_FAILED;
    }

It returns the length of the string (10) on Linux. But the same code is returning a positive number that is greater than the number of characters printed on HP-UX machine. Hope this explanation is fine.


Solution

  • you could create a snprintf wrapper that returns -1 for each case when there is not enough space in the buffer.

    See the man page for more docs. It has also an example which threats all the cases.

      while (1) {
          /* Try to print in the allocated space. */
          va_start(ap, fmt);
          n = vsnprintf (p, size, fmt, ap);
          va_end(ap);
          /* If that worked, return the string. */
          if (n > -1 && n < size)
             return p;
          /* 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 */
          if ((np = realloc (p, size)) == NULL) {
             free(p);
             return NULL;
          } else {
             p = np;
          }
       }