Bugtraq mailing list archives
Re: better snprintf replacement, anyone?
From: sten () ERGON CH (Sten Gunterberg)
Date: Tue, 22 Jul 1997 18:23:31 +0200
On 22nd July, James Bonfield <jkb () MRC-LMB CAM AC UK> wrote:
[...] I wrote a worst-cast scenario function to determine the maximum length of output for a sprintf style request. It doesn't handle unicode or anything fancy, but does handle most things reasonably well. I'm not saying it's 100% foolproof (eg it makes assumptions that we're not on anything bigger than a 64bit system), but it's a start.
Below follows some code I hacked together to do my own snprintf() *without* having to parse the format string. The performance freaks among you will frown on my waste of cycles, I'm sure :) --Sten /* * Variants of snprintf() and vsnprintf() with a definable callback * handler function to catch buffer overflows. * * Use it only if you have the "spare" cycles needed to effectively * do every snprintf operation twice! Why is that? Because everything * is first vfprintf()'d to /dev/null to determine the number of bytes. * Perhaps a bit slow for demanding applications on slow machines, * no problem for a fast machine with some spare cycles. * * You don't have a /dev/null? Every Linux contains one for free! * * On my Ultra-1 (143Mhz) this implementation of snprintf() runs * at 45% of the speed of native sprintf(). This leaves my with * "just" under 100k snprintf()'s per second to play with :-) * * Because the format string is never even looked at, all current and * possible future printf-conversions should be handled just fine. * * Written July 1997 by Sten Gunterberg (gunterberg () ergon ch) */ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> static void default_handler (const char *func, int max, const char *fmt) { int len; fprintf(stderr, "*** short buffer in %s() with max=%d and format=%s", func, max, fmt); if ((len = strlen(fmt)) > 0 && fmt[len-1] != '\n') fputc('\n', stderr); abort(); } static void (*overflow_handler)() = default_handler; void set_nprintf_overflow_handler (void (*arg)(const char *, int, const char *)) { overflow_handler = arg; } static int needed (const char *fmt, va_list argp) { static FILE *sink = NULL; if (sink == NULL) { if ((sink = fopen("/dev/null", "w")) == NULL) { /* Hmm. Find a better way to handle this! */ fprintf(stderr, "*** failed to open /dev/null ***\n"); abort(); } } return vfprintf(sink, fmt, argp); } int snprintf (char *buf, int max, const char *fmt, ...) { va_list argp; int bytes; va_start(argp, fmt); if (needed(fmt, argp) > max) { (*overflow_handler)("snprintf", max, fmt); exit(1); /* should never get here, really */ } bytes = vsprintf(buf, fmt, argp); va_end(argp); return bytes; } int vsnprintf (char *buf, int max, const char *fmt, va_list argp) { if (needed(fmt, argp) > max) { (*overflow_handler)("vsnprintf", max, fmt); exit(1); /* should never get here, really */ } return vsprintf(buf, fmt, argp); } #ifdef STANDALONE int main (int argc, char **argv) { char buf[10]; snprintf(buf, 10, "test %d\n", 123); /* works */ snprintf(buf, 10, "test %d\n", 123456); /* fails */ } #endif
Current thread:
- Re: better snprintf replacement, anyone?, (continued)
- 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? 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)