Use dynamic buffer sizes for formated CEXEBuild warning/error methods

git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6292 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
anders_k 2013-03-10 22:26:27 +00:00
parent a0cd389c78
commit 0d2edb2f1b
3 changed files with 104 additions and 26 deletions

View file

@ -492,7 +492,9 @@ int CEXEBuild::add_string(const TCHAR *string, int process/*=1*/, UINT codepage/
int i;
if (process)
{
TCHAR buf[NSIS_MAX_STRLEN*4];
ExpandoString<TCHAR, NSIS_MAX_STRLEN*4> buf;
// NOTE: It is impossible to know how much preprocessing will increase the size, we have to guess
buf.Reserve(_tcsclen(string) * 2);
preprocess_string(buf, string, codepage);
i = cur_strlist->add(buf, (WORD)codepage, true);
}
@ -3310,42 +3312,36 @@ bool IsStringASCII(const TCHAR* s)
void CEXEBuild::warning(const TCHAR *s, ...)
{
TCHAR buf[NSIS_MAX_STRLEN*10];
ExpandoString<TCHAR, NSIS_MAX_STRLEN + 100> buf;
va_list val;
va_start(val,s);
#ifdef _WIN32
_vstprintf(buf,s,val);
#else
_vsntprintf(buf,NSIS_MAX_STRLEN*10,s,val);
#endif
buf.StrFmt(s,val);
va_end(val);
m_warnings.add(buf,0);
notify(MAKENSIS_NOTIFY_WARNING,buf);
notify(MAKENSIS_NOTIFY_WARNING,buf.GetPtr());
if (display_warnings)
{
PrintColorFmtMsg_WARN(_T("warning: %s\n"),buf);
PrintColorFmtMsg_WARN(_T("warning: %s\n"),buf.GetPtr());
}
}
void CEXEBuild::warning_fl(const TCHAR *s, ...)
{
TCHAR buf[NSIS_MAX_STRLEN*10];
ExpandoString<TCHAR, NSIS_MAX_STRLEN + 100> buf;
va_list val;
va_start(val,s);
#ifdef _WIN32
_vstprintf(buf,s,val);
#else
_vsntprintf(buf,NSIS_MAX_STRLEN*10,s,val);
#endif
size_t cchMsg = buf.StrFmt(s,val);
va_end(val);
_stprintf(buf+_tcslen(buf),_T(" (%s:%d)"),curfilename,linecnt);
buf.Reserve(cchMsg+2+_tcslen(curfilename)+50+1+1);
_stprintf(&buf[cchMsg],_T(" (%s:%u)"),curfilename,linecnt);
m_warnings.add(buf,0);
notify(MAKENSIS_NOTIFY_WARNING,buf);
notify(MAKENSIS_NOTIFY_WARNING,buf.GetPtr());
if (display_warnings)
{
PrintColorFmtMsg_WARN(_T("warning: %s\n"),buf);
PrintColorFmtMsg_WARN(_T("warning: %s\n"),buf.GetPtr());
}
}
@ -3353,19 +3349,16 @@ void CEXEBuild::ERROR_MSG(const TCHAR *s, ...) const
{
if (display_errors || notify_hwnd)
{
TCHAR buf[NSIS_MAX_STRLEN*10];
ExpandoString<TCHAR, NSIS_MAX_STRLEN + 100> buf;
va_list val;
va_start(val,s);
#ifdef _WIN32
_vstprintf(buf,s,val);
#else
_vsntprintf(buf,NSIS_MAX_STRLEN*10,s,val);
#endif
buf.StrFmt(s,val);
va_end(val);
notify(MAKENSIS_NOTIFY_ERROR,buf);
notify(MAKENSIS_NOTIFY_ERROR,buf.GetPtr());
if (display_errors)
{
PrintColorFmtMsg_ERR(_T("%s"),buf);
PrintColorFmtMsg_ERR(_T("%s"),buf.GetPtr());
}
}
}

View file

@ -552,6 +552,67 @@ tstring lowercase(const tstring &str) {
return result;
}
/*
* ExpandoStrFmtVaList returns the number of characters written excluding
* the \0 terminator or 0 on error.
* realloc() is used on *ppMalloc if cchStack is not
* large enough to hold the formated string.
*/
size_t ExpandoStrFmtVaList(wchar_t*Stack, size_t cchStack, wchar_t**ppMalloc, const wchar_t*FmtStr, va_list Args)
{
#ifdef _WIN32
// For _vsnwprintf, the \0 terminator is not part of the size
#define ExpandoStrFmtVaList_vsnwprintf(d,c,f,v) _vsnwprintf((d),(c)?(c)-1:0,(f),(v))
#else
#define ExpandoStrFmtVaList_vsnwprintf vswprintf
#endif
#if defined(_ISOC99_SOURCE) || _POSIX_C_SOURCE >= 200112L
const bool cansizecalc = true, msvcbackdoor = false;
#else
static char testedsizecalc = 0;
if (!testedsizecalc)
{
#ifdef _WIN32
size_t cch = ExpandoStrFmtVaList_vsnwprintf(0, INT_MAX, L"333", Args);
#else
wchar_t testbuf[1+1];
size_t cch = ExpandoStrFmtVaList_vsnwprintf(testbuf, COUNTOF(testbuf), L"333", Args);
#endif
testedsizecalc = (3 == cch) + 1;
}
#ifdef _WIN32
const bool msvcbackdoor = !!(testedsizecalc - 1), cansizecalc = false;
#else
const bool cansizecalc = !!(testedsizecalc - 1), msvcbackdoor = false;
#endif
#endif
size_t &cchAvail = cchStack, cch;
wchar_t *&dest = Stack, *mem = *ppMalloc;
for(;;)
{
cch = ExpandoStrFmtVaList_vsnwprintf(dest, cchAvail, FmtStr, Args);
if (-1 == cch)
{
cch = 0;
if (cansizecalc) break; // vswprintf error, abort!
if (msvcbackdoor)
cchAvail = ExpandoStrFmtVaList_vsnwprintf(0, INT_MAX, FmtStr, Args) + 1;
else
cchAvail = 4 * STD_MAX(cchAvail, (size_t)500);
}
else
{
if (cch < cchAvail) break; // We are done.
cchAvail = ++cch; // cch from vswprintf did not include the \0 terminator
}
dest = mem = (wchar_t*) realloc(mem, cchAvail * sizeof(wchar_t));
if (!mem) return 0;
}
*ppMalloc = mem;
return cch;
}
int sane_system(const TCHAR *command) {
#ifdef _WIN32

View file

@ -56,6 +56,30 @@ tstring lowercase(const tstring&);
tstring get_string_prefix(const tstring& str, const tstring& separator);
tstring get_string_suffix(const tstring& str, const tstring& separator);
size_t ExpandoStrFmtVaList(wchar_t*Stack, size_t cchStack, wchar_t**ppMalloc, const wchar_t*FmtStr, va_list Args);
template<typename T, size_t S> class ExpandoString {
T m_stack[S ? S : 1], *m_heap;
public:
ExpandoString() : m_heap(0) {}
~ExpandoString() { free(m_heap); }
void Reserve(size_t cch)
{
if (S && cch <= S) return ;
void *p = realloc(m_heap, cch * sizeof(T));
if (!p) throw std::bad_alloc();
m_heap = (T*) p;
}
size_t StrFmt(const T*FmtStr, va_list Args)
{
size_t n = ExpandoStrFmtVaList(m_stack, COUNTOF(m_stack), &m_heap, FmtStr, Args);
if (!n && *FmtStr) throw std::bad_alloc();
return n;
}
T* GetPtr() { return m_heap ? m_heap : m_stack; }
operator T*() { return GetPtr(); }
};
int sane_system(const TCHAR *command);
void PrintColorFmtMsg(unsigned int type, const TCHAR *fmtstr, va_list args);