diff options
author | Andrew Tridgell <tridge@samba.org> | 1998-05-12 12:48:54 +0000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 1998-05-12 12:48:54 +0000 |
commit | 1dadc7af9534977c8c384fd3e54e506710fb3659 (patch) | |
tree | dcb17d07171b884cb259475b5504c63e6fad1c15 /source3/lib | |
parent | f888868f46a5418bac9ab528497136c152895305 (diff) | |
download | samba-1dadc7af9534977c8c384fd3e54e506710fb3659.tar.gz samba-1dadc7af9534977c8c384fd3e54e506710fb3659.tar.bz2 samba-1dadc7af9534977c8c384fd3e54e506710fb3659.zip |
a new slprintf() function. This one is totally portable but a bit of a
kludge. It is a safe kludge with our current code but I would like to
revisit it at some point in the future.
The problem with the one I committed yesterday is it used non-portable
functions. (it also had a bug in it, but that's another matter)
This one works by just using vsprintf() into a 8k buffer and a memcpy
from there. No memory protection tricks or other non-portable
stuff. This is safe because all calls to slprintf() in samba use
strings which have been through a pstrcpy and thus are less than 1024
bytes. No call uses more than 2 of these strings. See what I mean by
kludge? Note that the 8k is way overkill but I like overkill :)
Someday (after autoconf) we will replace this with something better,
but meanwhile this is simple, secure and portable.
(This used to be commit 4cfcc398c35c6726f14f485ae8e9ebcef180392f)
Diffstat (limited to 'source3/lib')
-rw-r--r-- | source3/lib/slprintf.c | 68 |
1 files changed, 41 insertions, 27 deletions
diff --git a/source3/lib/slprintf.c b/source3/lib/slprintf.c index 9a00585ca8..3a7e268046 100644 --- a/source3/lib/slprintf.c +++ b/source3/lib/slprintf.c @@ -23,47 +23,61 @@ extern int DEBUGLEVEL; + +/* this is like vsnprintf but the 'n' limit does not include + the terminating null. So if you have a 1024 byte buffer then + pass 1023 for n */ int vslprintf(char *str, int n, char *format, va_list ap) { #ifdef HAVE_VSNPRINTF int ret = vsnprintf(str, n, format, ap); - if (ret >= 0) str[ret] = 0; + if (ret > n || ret < 0) { + str[n] = 0; + return -1; + } + str[ret] = 0; return ret; #else static char *buf; - static int len; - static int pagesize; + static int len=8000; int ret; - if (!len || !buf || (len-pagesize) < n) { - pagesize = getpagesize(); - len = (2+(n/pagesize))*pagesize; - /* note: we don't free the old memory (if any) as we don't - want a malloc lib to reuse the memory as it will - have the wrong permissions */ -#ifdef HAVE_MEMALIGN - buf = memalign(pagesize, len); -#else /* HAVE_MEMALIGN */ -#ifdef HAVE_VALLOC - buf = valloc(len); -#else /* HAVE_VALLOC */ - buf = malloc(len); -#endif /* HAVE_VALLOC */ -#endif /* HAVE_MEMALIGN */ - if (buf) { - if (mprotect(buf+(len-pagesize), pagesize, PROT_READ) != 0) { - exit(1); - return -1; - } + /* this code is NOT a proper vsnprintf() implementation. It + relies on the fact that all calls to slprintf() in Samba + pass strings which have already been through pstrcpy() or + fstrcpy() and never more than 2 strings are + concatenated. This means the above buffer is absolutely + ample and can never be overflowed. + + In the future we would like to replace this with a proper + vsnprintf() implementation but right now we need a solution + that is secure and portable. This is it. */ + + if (!buf) { + buf = malloc(len); + if (!buf) { + /* can't call debug or we would recurse */ + exit(1); } } - if (!buf) { - exit(1); + ret = vsprintf(buf, format, ap); + + if (ret < 0) { + str[0] = 0; + return -1; } - ret = vsprintf(str, format, ap); - /* we will have got a seg fault here if we overflowed the buffer */ + if (ret < n) { + n = ret; + } else if (ret > n) { + ret = -1; + } + + buf[n] = 0; + + memcpy(str, buf, n+1); + return ret; #endif } |