Bugtraq mailing list archives
Re: better snprintf replacement, anyone?
From: casper () HOLLAND SUN COM (Casper Dik)
Date: Wed, 23 Jul 1997 15:28:57 +0200
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.
Typical system V implementations (as well as older BSD implementations) have an unsafe tmpfile(). This is true for Solaris (before 2.6 when we fixed it) and in IRIX (last time I looked). Perhaps we can check and compile a list?
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!)
This is also a problem as many implementations expect snprintf() to always return a positive count; either bytes required (possible > n) That's one of the more difficult things of implementing a new function; what willbe teh exact semantics? (the 2.5/2.5.1 __* function has slightly different semantcis than the public 2.6 *snprintf()) Here's one I did and it also uses temporary files, but it uses "mkstemp()" which should be save. BTW, mkstemp() always uses open(,, 0600) so you get private tmpfiles; tmpfile() is required to use the umask() in setting the mode. Depending on how this is implemented, there's a window in which a tmpfile() can be opened by other processes. A naive reimplementation of tmpfile() using mkstemp() fails the standard conformance tests. (s = mkstemp(template); unlink(template); return fdopen(s,"w+)). Solaris 2.6 does use mkstemp() but does an fchmod() after unlink()ing the file so there's no race condition either. Standard are stupid sometimes. /* * snprintf() quicky using temporary files. * Not stress tested, but it seems to work. * * Returns the number of bytes that would have been output by printf. * Does not check whether a negative value if passed in for n (as it's unsigned); * some implementations cast n to int and than compare with 0. * * Casper Dik (Casper.Dik () Holland Sun COM) */ #include <stdarg.h> #include <stdlib.h> #include <stdio.h> int snprintf(char * buf, size_t n, const char *fmt, ...) { va_list ap; int ret; va_start(ap, fmt); ret = vsnprintf(buf, n, fmt, ap); va_end(ap); return ret; } static char template[] = "/tmp/snprintfXXXXXX"; int vsnprintf(char *buf, size_t n, const char *fmt, va_list ap) { char templ[sizeof(template)]; int s; int ret, cnt = 0, nread; FILE *fp; strcpy(templ,template); s = mkstemp(templ); if (s < 0) return -1; (void) unlink(templ); fp = fdopen(s, "w+"); if (fp == NULL) { close(s); return -1; } ret = vfprintf(fp, fmt, ap); if (ret < 0 || fseek(fp, 0, SEEK_SET) < 0) { fclose(fp); return -1; } while (cnt < n && (nread = fread(buf + cnt, 1, n - cnt, fp)) > 0) cnt += nread; buf[cnt-1] = '\0'; /* cnt is atmost n */ fclose(fp); return ret; }
Current thread:
- Re: better snprintf replacement, anyone?, (continued)
- 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? 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)