Fixes for wxVsnprintf not always null terminating and not always copying as much
as will fit. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@43294 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -993,19 +993,23 @@ int wxPrintfConvSpec::Process(wxChar *buf, size_t lenMax, wxPrintfArg *p, size_t
|
|||||||
return lenCur;
|
return lenCur;
|
||||||
}
|
}
|
||||||
|
|
||||||
// differences from standard strncpy:
|
// Copy chars from source to dest converting '%%' to '%'. Takes at most maxIn
|
||||||
// 1) copies everything from 'source' except for '%%' sequence which is copied as '%'
|
// chars from source and write at most outMax chars to dest, returns the
|
||||||
// 2) returns the number of written characters in 'dest' as it could differ from given 'n'
|
// number of chars actually written. Does not treat null specially.
|
||||||
// 3) much less optimized, unfortunately...
|
//
|
||||||
static int wxCopyStrWithPercents(wxChar *dest, const wxChar *source, size_t n)
|
static int wxCopyStrWithPercents(
|
||||||
|
size_t maxOut,
|
||||||
|
wxChar *dest,
|
||||||
|
size_t maxIn,
|
||||||
|
const wxChar *source)
|
||||||
{
|
{
|
||||||
size_t written = 0;
|
size_t written = 0;
|
||||||
|
|
||||||
if (n == 0)
|
if (maxIn == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
size_t i;
|
size_t i;
|
||||||
for ( i = 0; i < n-1; source++, i++)
|
for ( i = 0; i < maxIn-1 && written < maxOut; source++, i++)
|
||||||
{
|
{
|
||||||
dest[written++] = *source;
|
dest[written++] = *source;
|
||||||
if (*(source+1) == wxT('%'))
|
if (*(source+1) == wxT('%'))
|
||||||
@@ -1016,7 +1020,7 @@ static int wxCopyStrWithPercents(wxChar *dest, const wxChar *source, size_t n)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i < n)
|
if (i < maxIn && written < maxOut)
|
||||||
// copy last character inconditionally
|
// copy last character inconditionally
|
||||||
dest[written++] = *source;
|
dest[written++] = *source;
|
||||||
|
|
||||||
@@ -1097,8 +1101,10 @@ int WXDLLEXPORT wxVsnprintf_(wxChar *buf, size_t lenMax,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (posarg_present && nonposarg_present)
|
if (posarg_present && nonposarg_present)
|
||||||
|
{
|
||||||
|
buf[0] = 0;
|
||||||
return -1; // format strings with both positional and
|
return -1; // format strings with both positional and
|
||||||
// non-positional conversion specifier are unsupported !!
|
} // non-positional conversion specifier are unsupported !!
|
||||||
|
|
||||||
// on platforms where va_list is an array type, it is necessary to make a
|
// on platforms where va_list is an array type, it is necessary to make a
|
||||||
// copy to be able to pass it to LoadArg as a reference.
|
// copy to be able to pass it to LoadArg as a reference.
|
||||||
@@ -1119,7 +1125,10 @@ int WXDLLEXPORT wxVsnprintf_(wxChar *buf, size_t lenMax,
|
|||||||
|
|
||||||
// something failed while loading arguments from the variable list...
|
// something failed while loading arguments from the variable list...
|
||||||
if (!ok)
|
if (!ok)
|
||||||
|
{
|
||||||
|
buf[0] = 0;
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
// finally, process each conversion specifier with its own argument
|
// finally, process each conversion specifier with its own argument
|
||||||
toparse = format;
|
toparse = format;
|
||||||
@@ -1128,19 +1137,17 @@ int WXDLLEXPORT wxVsnprintf_(wxChar *buf, size_t lenMax,
|
|||||||
// copy in the output buffer the portion of the format string between
|
// copy in the output buffer the portion of the format string between
|
||||||
// last specifier and the current one
|
// last specifier and the current one
|
||||||
size_t tocopy = ( arg[i].m_pArgPos - toparse );
|
size_t tocopy = ( arg[i].m_pArgPos - toparse );
|
||||||
if (lenCur+tocopy >= lenMax)
|
|
||||||
|
lenCur += wxCopyStrWithPercents(lenMax - lenCur, buf + lenCur,
|
||||||
|
tocopy, toparse);
|
||||||
|
if (lenCur == lenMax)
|
||||||
{
|
{
|
||||||
// not enough space in the output buffer !
|
buf[lenMax - 1] = 0;
|
||||||
// copy until the end of remaining space and then stop
|
|
||||||
wxCopyStrWithPercents(buf+lenCur, toparse, lenMax - lenCur - 1);
|
|
||||||
buf[lenMax-1] = wxT('\0');
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
lenCur += wxCopyStrWithPercents(buf+lenCur, toparse, tocopy);
|
|
||||||
|
|
||||||
// process this specifier directly in the output buffer
|
// process this specifier directly in the output buffer
|
||||||
int n = arg[i].Process(buf+lenCur, lenMax - lenCur, &argdata[arg[i].m_pos]);
|
int n = arg[i].Process(buf+lenCur, lenMax - lenCur, &argdata[arg[i].m_pos], lenCur);
|
||||||
if (n == -1)
|
if (n == -1)
|
||||||
{
|
{
|
||||||
buf[lenMax-1] = wxT('\0'); // be sure to always NUL-terminate the string
|
buf[lenMax-1] = wxT('\0'); // be sure to always NUL-terminate the string
|
||||||
@@ -1158,11 +1165,14 @@ int WXDLLEXPORT wxVsnprintf_(wxChar *buf, size_t lenMax,
|
|||||||
// conversion specifier
|
// conversion specifier
|
||||||
// NOTE2: the +1 is because we want to copy also the '\0'
|
// NOTE2: the +1 is because we want to copy also the '\0'
|
||||||
size_t tocopy = wxStrlen(format) + 1 - ( toparse - format ) ;
|
size_t tocopy = wxStrlen(format) + 1 - ( toparse - format ) ;
|
||||||
if (lenCur+tocopy >= lenMax)
|
|
||||||
return -1; // not enough space in the output buffer !
|
|
||||||
|
|
||||||
// the -1 is because of the '\0'
|
lenCur += wxCopyStrWithPercents(lenMax - lenCur, buf + lenCur,
|
||||||
lenCur += wxCopyStrWithPercents(buf+lenCur, toparse, tocopy) - 1;
|
tocopy, toparse) - 1;
|
||||||
|
if (buf[lenCur])
|
||||||
|
{
|
||||||
|
buf[lenCur] = 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
wxASSERT(lenCur == wxStrlen(buf));
|
wxASSERT(lenCur == wxStrlen(buf));
|
||||||
return lenCur;
|
return lenCur;
|
||||||
|
Reference in New Issue
Block a user