Bugtraq mailing list archives
Re: better snprintf replacement, anyone?
From: rugolsky () EAD DSA COM (Bill Rugolsky Jr.)
Date: Tue, 22 Jul 1997 09:30:05 -0400
On Sat, 19 Jul 1997, Theo de Raadt wrote:
Quite often I find people saying to me "Why do you use snprintf() all over the place to avoid buffer overflows, and not try to use other techniques. Using snprintf() makes it hard for us to port the code to legacy systems."
A while back I threw together these short routines, which have worked quite well in practice. The return value conventions probably don't correspond to the BSD snprintf(), because I didn't have any documentation available. The principal virtue is that they produce results identical to the native printf() implementation. They were not written with security in mind, though. A poor implementation of tmpfile() could open up numerous security holes. Hope you find them useful. Bill Rugolsky rugolsky () ead dsa com ------------------------------ cut here ------------------------------ #include <stdio.h> #include <stdarg.h> #include <errno.h> #include <malloc.h> /* The variable "snprintf_bufsiz" may be set prior to calling any of these functions. Set this value large enough to avoid doing any system calls. */ size_t snprintf_bufsiz = 4*BUFSIZ; static FILE *fp; /* temporary file used as a buffer */ static FILE * getfilebuffer() { FILE *f; if ((f = tmpfile()) != NULL) setvbuf(f,NULL,_IOFBF,snprintf_bufsiz); return f; } /* [v]snprintf: A safe alternative to [v]sprintf. This version is may be significantly slower, especially on SunOS, where the implementation of stdio is sub-optimal. In particular, rewind() may generate a system call (aargh!). A good implementation of stdio will incur only a memcpy() penalty from the fread(). If the null-terminated string fits inside of the buffer, returns the string length (not counting the terminating '\0'). If the string exceeds the buffer length, errno is set to ENOMEM and the negative string length is returned. The first len-1 characters are placed in the buffer. (Add one for the terminating '\0' when allocating a buffer!) Any other error causes the function to set errno and return -1. */ int vsnprintf(char buf[], size_t len, const char fmt[], va_list args) { int actual; if(!buf || len < 1) { errno = EINVAL; return -1; } if (!fp && !(fp = getfilebuffer())) return -1; rewind(fp); actual = vfprintf(fp,fmt,args); rewind(fp); if (actual < 0) return -1; else if (actual < len) len = actual; else --len; if (len > 0 && fread(buf,1,len,fp) != len) return -1; buf[len] = '\0'; if (actual > len) { errno = ENOMEM; return -actual; } return actual; } int snprintf(char buf[], size_t len, const char fmt[], ...) { int rv; va_list args; va_start(args,fmt); rv = vsnprintf(buf,len,fmt,args); va_end(args); return rv; } /* [v]mprintf: format string into a buffer allocated using malloc(). */ char * vmprintf(const char fmt[], va_list args) { int actual; char *buf; if (!fp && !(fp = getfilebuffer())) return NULL; rewind(fp); actual = vfprintf(fp,fmt,args); rewind(fp); if (actual < 0) return NULL; if (!(buf = malloc(actual+1))) return NULL; if (fread(buf,1,actual,fp) != actual) { free(buf); return NULL; } buf[actual] = '\0'; return buf; } char * mprintf(const char fmt[], ...) { char *s; va_list args; va_start(args,fmt); s = vmprintf(fmt,args); va_end(args); return s; }
Current thread:
- Re: better snprintf replacement, anyone?, (continued)
- Re: better snprintf replacement, anyone? Steve \ (Jul 21)
- Re: better snprintf replacement, anyone? Manoj Kasichainula (Jul 21)
- Re: better snprintf replacement, anyone? Theo de Raadt (Jul 21)
- Re: better snprintf replacement, anyone? Alan Cox (Jul 22)
- Re: better snprintf replacement, anyone? James Bonfield (Jul 22)
- ld.so vulnerability Aleph One (Jul 22)
- Security hole in exim 1.62: local root exploit Aleph One (Jul 22)
- Re: Security hole in exim 1.62: local root exploit Warner Losh (Jul 22)
- Named Config Files Gus Huber (Jul 22)
- Re: Named Config Files Aveek Datta (Jul 22)
- Re: better snprintf replacement, anyone? Steve \ (Jul 21)
- Re: better snprintf replacement, anyone? Bill Rugolsky Jr. (Jul 22)
- Re: better snprintf replacement, anyone? Casper Dik (Jul 23)
- Re: better snprintf replacement, anyone? der Mouse (Jul 22)
- Re: better snprintf replacement, anyone? Sten Gunterberg (Jul 22)
- Re: better snprintf replacement, anyone? Peter Jeremy (Jul 22)
- Re: better snprintf replacement, anyone? Theo de Raadt (Jul 22)
- Re: better snprintf replacement, anyone? der Mouse (Jul 22)