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)
