diff options
-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 } |