add safe wxStrlcpy() function and replaced all wxStrncpy() calls by it

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@57023 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2008-11-29 14:41:02 +00:00
parent 56ce942b62
commit e408bf5257
27 changed files with 126 additions and 89 deletions

View File

@@ -231,6 +231,36 @@ inline char *wxStrncpy(char *dest, const wchar_t *src, size_t n)
inline wchar_t *wxStrncpy(wchar_t *dest, const char *src, size_t n)
{ return wxCRT_StrncpyW(dest, wxConvLibc.cMB2WC(src), n); }
// this is a new function so we don't care about backwards compatibility and
// so don't need to support wchar_t/char overloads
inline size_t wxStrlcpy(char *dest, const char *src, size_t n)
{
const size_t len = wxCRT_StrlenA(src);
if ( n )
{
if ( n-- > len )
n = len;
wxCRT_StrncpyA(dest, src, n);
dest[n] = '\0';
}
return len;
}
inline size_t wxStrlcpy(wchar_t *dest, const wchar_t *src, size_t n)
{
const size_t len = wxCRT_StrlenW(src);
if ( n )
{
if ( n-- > len )
n = len;
wxCRT_StrncpyW(dest, src, n);
dest[n] = L'\0';
}
return len;
}
inline char *wxStrcat(char *dest, const char *src)
{ return wxCRT_StrcatA(dest, src); }
inline wchar_t *wxStrcat(wchar_t *dest, const wchar_t *src)

View File

@@ -86,6 +86,56 @@ wxArrayString wxStringTokenize(const wxString& string,
const wxString& delims = wxDEFAULT_DELIMITERS,
wxStringTokenizerMode mode = wxTOKEN_DEFAULT);
/**
Safe and more convenient replacement for strncpy().
This function copies the source string @a src to the destination buffer @a
dst of size @a n without overflowing the buffer and ensuring that it is
always @NUL-terminated.
Example of use:
@code
char buf[256];
if ( wxStrlcpy(buf, GetSomeString(), WXSIZEOF(buf)) > WXSIZEOF(buf) )
... handle truncation ...
@endcode
Notice that using wxStrncpy() in similar way is wrong, the above is broadly
equivalent to
@code
char buf[256];
buf[WXSIZEOF(buf) - 1] = '\0';
wxStrncpy(buf, GetSomeString(), WXSIZEOF(buf) - 1);
if ( buf[WXSIZEOF(buf) - 1] != '\0' )
{
... truncation occurred ...
// need to NUL-terminate string manually
buf[WXSIZEOF(buf) - 1] = '\0';
}
@endcode
which should explain the advantage of using wxStrlcpy().
Notice that this function is similar to the OpenBSD strlcpy() function.
The template parameter @a T can be either @c char or @c wchar_t.
@param dst
Destination buffer of size (greater or) equal to @a n.
@param src
@NUL-terminated source string.
@param n
The size of the destination buffer.
@return
The length of @a src, if the returned value is greater or equal to @a n
then there was not enough space in the destination buffer and the
string was truncated.
@since{2.9.0}
@header{wx/wxcrt.h}
*/
template <typename T>
size_t wxStrlcpy(T *dst, const T *src, size_t n);
/**
This function replaces the dangerous standard function @e sprintf() and is
like @e snprintf() available on some platforms. The only difference with

View File

@@ -381,7 +381,7 @@ extern const char *wxDumpDate(const wxDateTime* dt)
static char buf[128];
wxString fmt(dt->Format("%Y-%m-%d (%a) %H:%M:%S"));
wxStrncpy(buf, fmt + " (" + dt->GetValue().ToString() + " ticks)",
wxStrlcpy(buf, fmt + " (" + dt->GetValue().ToString() + " ticks)",
WXSIZEOF(buf));
return buf;

View File

@@ -1068,8 +1068,7 @@ const wxChar *wxSysErrorMsg(unsigned long nErrCode)
#if !defined(__SMARTPHONE__) /* of WinCE */
if( lpMsgBuf != 0 )
{
wxStrncpy(s_szBuf, (const wxChar *)lpMsgBuf, WXSIZEOF(s_szBuf) - 1);
s_szBuf[WXSIZEOF(s_szBuf) - 1] = wxS('\0');
wxStrlcpy(s_szBuf, (const wxChar *)lpMsgBuf, WXSIZEOF(s_szBuf));
LocalFree(lpMsgBuf);

View File

@@ -436,8 +436,7 @@ bool wxGetEmailAddress(wxChar *address, int maxSize)
if ( !email )
return false;
wxStrncpy(address, email, maxSize - 1);
address[maxSize - 1] = wxT('\0');
wxStrlcpy(address, email, maxSize);
return true;
}

View File

@@ -149,7 +149,7 @@ wxDataFormat wxRegisterClipboardFormat(char *WXUNUSED(formatName))
bool wxGetClipboardFormatName(const wxDataFormat& dataFormat, char *formatName,
int maxCount)
{
wxStrncpy( formatName, dataFormat.GetId().c_str(), maxCount );
wxStrlcpy( formatName, dataFormat.GetId().c_str(), maxCount );
return true;
}

View File

@@ -233,7 +233,7 @@ bool wxGetUserId(wxChar *buf, int n)
if (!user)
user = _T("user");
wxStrncpy(buf, user, n);
wxStrlcpy(buf, user, n);
return true;
}
@@ -254,7 +254,7 @@ bool wxGetHostName(wxChar *buf, int n)
if (!host)
host = _T("host");
wxStrncpy(buf, host, n);
wxStrlcpy(buf, host, n);
return true;
}

View File

@@ -664,8 +664,8 @@ static void RegisterAndStoreClassName(const wxString& uniqueClassName,
WNDCLASS *lpWndClass)
{
const size_t length = uniqueClassName.length() + 1; // for trailing NUL
wxChar *newChars = new wxChar[length];
wxStrncpy(newChars, uniqueClassName, length);
wxChar * const newChars = new wxChar[length];
wxStrlcpy(newChars, uniqueClassName, length);
*className = newChars;
lpWndClass->lpszClassName = *className;

View File

@@ -247,8 +247,7 @@ bool wxCrashReportImpl::Generate(int flags, EXCEPTION_POINTERS *ep)
/* static */
void wxCrashReport::SetFileName(const wxString& filename)
{
wxStrncpy(gs_reportFilename, filename.c_str(), WXSIZEOF(gs_reportFilename) - 1);
gs_reportFilename[WXSIZEOF(gs_reportFilename) - 1] = _T('\0');
wxStrlcpy(gs_reportFilename, filename.wx_str(), WXSIZEOF(gs_reportFilename));
}
/* static */

View File

@@ -807,7 +807,7 @@ bool wxDialUpManagerMSW::Dial(const wxString& nameOfISP,
RASDIALPARAMS rasDialParams;
rasDialParams.dwSize = sizeof(rasDialParams);
wxStrncpy(rasDialParams.szEntryName, entryName, RAS_MaxEntryName);
wxStrlcpy(rasDialParams.szEntryName, entryName, RAS_MaxEntryName);
// do we have the username and password?
if ( !username || !password )
@@ -829,8 +829,8 @@ bool wxDialUpManagerMSW::Dial(const wxString& nameOfISP,
}
else
{
wxStrncpy(rasDialParams.szUserName, username, UNLEN);
wxStrncpy(rasDialParams.szPassword, password, PWLEN);
wxStrlcpy(rasDialParams.szUserName, username, UNLEN);
wxStrlcpy(rasDialParams.szPassword, password, PWLEN);
}
// default values for other fields

View File

@@ -494,8 +494,7 @@ int wxFileDialog::ShowModal()
//=== Setting defaultFileName >>=========================================
wxStrncpy(fileNameBuffer, m_fileName, wxMAXPATH-1);
fileNameBuffer[ wxMAXPATH-1 ] = wxT('\0');
wxStrlcpy(fileNameBuffer, m_fileName, WXSIZEOF(fileNameBuffer));
of.lpstrFile = fileNameBuffer; // holds returned filename
of.nMaxFile = wxMAXPATH;
@@ -596,8 +595,7 @@ int wxFileDialog::ShowModal()
extension = extension + wxStrlen( extension ) + 1;
m_fileName = AppendExtension(fileNameBuffer, extension);
wxStrncpy(fileNameBuffer, m_fileName.c_str(), wxMin(m_fileName.length(), wxMAXPATH-1));
fileNameBuffer[wxMin(m_fileName.length(), wxMAXPATH-1)] = wxT('\0');
wxStrlcpy(fileNameBuffer, m_fileName.c_str(), WXSIZEOF(fileNameBuffer));
}
m_path = fileNameBuffer;

View File

@@ -618,9 +618,7 @@ void wxNativeFontInfo::SetUnderlined(bool underlined)
bool wxNativeFontInfo::SetFaceName(const wxString& facename)
{
size_t len = WXSIZEOF(lf.lfFaceName);
wxStrncpy(lf.lfFaceName, facename, len);
lf.lfFaceName[len - 1] = '\0'; // truncate the face name
wxStrlcpy(lf.lfFaceName, facename, WXSIZEOF(lf.lfFaceName));
return true;
}

View File

@@ -166,7 +166,7 @@ void wxFontEnumeratorHelper::DoEnumerate()
#else // __WIN32__
LOGFONT lf;
lf.lfCharSet = (BYTE)m_charset;
wxStrncpy(lf.lfFaceName, m_facename, WXSIZEOF(lf.lfFaceName));
wxStrlcpy(lf.lfFaceName, m_facename, WXSIZEOF(lf.lfFaceName));
lf.lfPitchAndFamily = 0;
::EnumFontFamiliesEx(hDC, &lf, (wxFONTENUMPROC)wxFontEnumeratorProc,
(LPARAM)this, 0 /* reserved */) ;

View File

@@ -162,7 +162,7 @@ bool wxTestFontEncoding(const wxNativeEncodingInfo& info)
wxZeroMemory(lf); // all default values
lf.lfCharSet = (BYTE)info.charset;
wxStrncpy(lf.lfFaceName, info.facename, WXSIZEOF(lf.lfFaceName));
wxStrlcpy(lf.lfFaceName, info.facename, WXSIZEOF(lf.lfFaceName));
HFONT hfont = ::CreateFontIndirect(&lf);
if ( !hfont )

View File

@@ -2485,8 +2485,7 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
if ( lvi.mask & LVIF_TEXT )
{
wxString text = OnGetItemText(item, lvi.iSubItem);
wxStrncpy(lvi.pszText, text, lvi.cchTextMax - 1);
lvi.pszText[lvi.cchTextMax - 1] = _T('\0');
wxStrlcpy(lvi.pszText, text, lvi.cchTextMax);
}
// see comment at the end of wxListCtrl::GetColumn()

View File

@@ -412,10 +412,9 @@ bool wxWindowsPrintNativeData::TransferFrom( const wxPrintData &data )
{
// NB: the cast is needed in the ANSI build, strangely enough
// dmDeviceName is BYTE[] and not char[] there
wxStrncpy(reinterpret_cast<wxChar *>(devMode->dmDeviceName),
wxStrlcpy(reinterpret_cast<wxChar *>(devMode->dmDeviceName),
name.wx_str(),
WXSIZEOF(devMode->dmDeviceName) - 1);
devMode->dmDeviceName[WXSIZEOF(devMode->dmDeviceName) - 1] = wxT('\0');
WXSIZEOF(devMode->dmDeviceName));
}
//// Colour

View File

@@ -197,7 +197,7 @@ bool wxTaskBarIcon::SetIcon(const wxIcon& icon, const wxString& tooltip)
notifyData.uFlags |= NIF_TIP;
if ( !tooltip.empty() )
{
wxStrncpy(notifyData.szTip, tooltip.wx_str(), WXSIZEOF(notifyData.szTip));
wxStrlcpy(notifyData.szTip, tooltip.wx_str(), WXSIZEOF(notifyData.szTip));
}
bool ok = wxShellNotifyIcon(m_iconAdded ? NIM_MODIFY
@@ -235,8 +235,8 @@ wxTaskBarIcon::ShowBalloon(const wxString& title,
notifyData = NotifyIconData(hwnd);
notifyData.uFlags |= NIF_INFO;
notifyData.uTimeout = msec;
wxStrncpy(notifyData.szInfo, text.wx_str(), WXSIZEOF(notifyData.szInfo));
wxStrncpy(notifyData.szInfoTitle, title.wx_str(),
wxStrlcpy(notifyData.szInfo, text.wx_str(), WXSIZEOF(notifyData.szInfo));
wxStrlcpy(notifyData.szInfoTitle, title.wx_str(),
WXSIZEOF(notifyData.szInfoTitle));
if ( flags & wxICON_INFORMATION )

View File

@@ -2447,7 +2447,7 @@ bool wxTextCtrl::SetStyle(long start, long end, const wxTextAttr& style)
cf.yHeight = 20*font.GetPointSize(); // 1 pt = 20 twips
cf.bCharSet = lf.lfCharSet;
cf.bPitchAndFamily = lf.lfPitchAndFamily;
wxStrncpy( cf.szFaceName, lf.lfFaceName, WXSIZEOF(cf.szFaceName) );
wxStrlcpy(cf.szFaceName, lf.lfFaceName, WXSIZEOF(cf.szFaceName));
// also deal with underline/italic/bold attributes: note that we must
// always set CFM_ITALIC &c bits in dwMask, even if we don't set the

View File

@@ -132,7 +132,7 @@ bool wxGetHostName(wxChar *WXUNUSED_IN_WINCE(buf),
#if defined(__WXWINCE__)
// TODO-CE
return false;
#elif defined(__WIN32__) && !defined(__WXMICROWIN__)
#else
DWORD nSize = maxSize;
if ( !::GetComputerName(buf, &nSize) )
{
@@ -142,16 +142,6 @@ bool wxGetHostName(wxChar *WXUNUSED_IN_WINCE(buf),
}
return true;
#else
wxChar *sysname;
const wxChar *default_host = wxT("noname");
if ((sysname = wxGetenv(wxT("SYSTEM_NAME"))) == NULL) {
GetProfileString(WX_SECTION, eHOSTNAME, default_host, buf, maxSize - 1);
} else
wxStrncpy(buf, sysname, maxSize - 1);
buf[maxSize] = wxT('\0');
return *buf ? true : false;
#endif
}
@@ -228,7 +218,7 @@ bool wxGetFullHostName(wxChar *buf, int maxSize)
if ( !host.empty() )
{
wxStrncpy(buf, host, maxSize);
wxStrlcpy(buf, host, maxSize);
return true;
}
@@ -246,7 +236,7 @@ bool wxGetUserId(wxChar *WXUNUSED_IN_WINCE(buf),
#if defined(__WXWINCE__)
// TODO-CE
return false;
#elif defined(__WIN32__) && !defined(__WXMICROWIN__)
#else
DWORD nSize = maxSize;
if ( ::GetUserName(buf, &nSize) == 0 )
{
@@ -260,24 +250,6 @@ bool wxGetUserId(wxChar *WXUNUSED_IN_WINCE(buf),
}
return true;
#else // __WXMICROWIN__
wxChar *user;
const wxChar *default_id = wxT("anonymous");
// Can't assume we have NIS (PC-NFS) or some other ID daemon
// So we ...
if ( (user = wxGetenv(wxT("USER"))) == NULL &&
(user = wxGetenv(wxT("LOGNAME"))) == NULL )
{
// Use wxWidgets configuration data (comming soon)
GetProfileString(WX_SECTION, eUSERID, default_id, buf, maxSize - 1);
}
else
{
wxStrncpy(buf, user, maxSize - 1);
}
return *buf ? true : false;
#endif
}
@@ -294,8 +266,7 @@ bool wxGetUserName(wxChar *buf, int maxSize)
wxString name;
if(!key.QueryValue(wxT("Owner"),name))
return false;
wxStrncpy(buf, name.c_str(), maxSize-1);
buf[maxSize-1] = _T('\0');
wxStrlcpy(buf, name.c_str(), maxSize);
return true;
#elif defined(USE_NET_API)
CHAR szUserName[256];
@@ -374,7 +345,7 @@ error:
if ( !ok )
{
wxStrncpy(buf, wxT("Unknown User"), maxSize);
wxStrlcpy(buf, wxT("Unknown User"), maxSize);
}
return true;

View File

@@ -123,10 +123,9 @@ wxChar *wxLoadUserResource(const wxString& resourceName, const wxString& resourc
// Not all compilers put a zero at the end of the resource (e.g. BC++ doesn't).
// so we need to find the length of the resource.
int len = ::SizeofResource(wxGetInstance(), hResource);
wxChar *s = new wxChar[len+1];
wxStrncpy(s,theText,len);
s[len]=0;
int len = ::SizeofResource(wxGetInstance(), hResource) + 1;
wxChar *s = new wxChar[len];
wxStrlcpy(s, theText, len);
// Obsolete in WIN32
#ifndef __WIN32__

View File

@@ -3850,8 +3850,7 @@ bool wxWindowMSW::HandleTooltipNotify(WXUINT code,
// if we got TTN_NEEDTEXTW in Unicode build: in this case we just have
// to copy the string we have into the buffer
static wxChar buf[513];
wxStrncpy(buf, ttip.c_str(), WXSIZEOF(buf) - 1);
buf[WXSIZEOF(buf) - 1] = _T('\0');
wxStrlcpy(buf, ttip.c_str(), WXSIZEOF(buf));
ttText->lpszText = buf;
}

View File

@@ -697,7 +697,7 @@ bool wxNativeFontInfo::SetFaceName(
const wxString& sFacename
)
{
wxStrncpy((wxChar*)fa.szFacename, sFacename, WXSIZEOF(fa.szFacename));
wxStrlcpy((wxChar*)fa.szFacename, sFacename, WXSIZEOF(fa.szFacename));
return true;
} // end of wxNativeFontInfo::SetFaceName

View File

@@ -120,7 +120,7 @@ void wxFontEnumeratorHelper::DoEnumerate()
#ifdef __WIN32__
LOGFONT lf;
lf.lfCharSet = m_charset;
wxStrncpy(lf.lfFaceName, m_facename, WXSIZEOF(lf.lfFaceName));
wxStrlcpy(lf.lfFaceName, m_facename, WXSIZEOF(lf.lfFaceName));
lf.lfPitchAndFamily = 0;
::EnumFontFamiliesEx(hDC, &lf, (wxFONTENUMPROC)wxFontEnumeratorProc,
(LPARAM)this, 0) ;

View File

@@ -233,7 +233,7 @@ bool wxTestFontEncoding( const wxNativeEncodingInfo& rInfo )
vLogFont.fsFontUse = FATTR_FONTUSE_OUTLINE | // only outline fonts allowed
FATTR_FONTUSE_TRANSFORMABLE; // may be transformed
wxStrncpy((wxChar*)vLogFont.szFacename, rInfo.facename.c_str(), WXSIZEOF(vLogFont.szFacename));
wxStrlcpy((wxChar*)vLogFont.szFacename, rInfo.facename.c_str(), WXSIZEOF(vLogFont.szFacename));
if (!::GpiCreateLogFont( hPS
,NULL
@@ -549,7 +549,7 @@ void wxOS2SelectMatchingFontByName(
break;
}
wxStrncpy(zFontFaceName, sFaceName.c_str(), WXSIZEOF(zFontFaceName));
wxStrlcpy(zFontFaceName, sFaceName.c_str(), WXSIZEOF(zFontFaceName));
nPointSize = pFont->GetPointSize();
//

View File

@@ -93,13 +93,12 @@ bool wxGetHostName( wxChar* zBuf, int nMaxSize )
,(void*)zBuf
,(ULONG)nMaxSize - 1
);
zBuf[nMaxSize] = _T('\0');
}
else
{
wxStrncpy(zBuf, zSysname, nMaxSize - 1);
wxStrlcpy(zBuf, zSysname, nMaxSize);
}
zBuf[nMaxSize] = _T('\0');
#endif
return *zBuf ? true : false;
@@ -121,7 +120,7 @@ bool wxGetUserName( wxChar* zBuf, int nMaxSize )
#ifdef USE_NET_API
wxGetUserId( zBuf, nMaxSize );
#else
wxStrncpy(zBuf, _T("Unknown User"), nMaxSize);
wxStrlcpy(zBuf, _T("Unknown User"), nMaxSize);
#endif
return true;
}

View File

@@ -97,7 +97,7 @@ bool wxGetUserName(wxChar *buf, int maxSize)
return false;
}
wxStrncpy (buf, wxSafeConvertMB2WX(id), maxSize - 1);
wxStrlcpy(buf, wxSafeConvertMB2WX(id), maxSize);
// free the buffer
MemPtrUnlock(id);

View File

@@ -777,16 +777,14 @@ static bool wxGetHostNameInternal(wxChar *buf, int sz)
bool ok = uname(&uts) != -1;
if ( ok )
{
wxStrncpy(buf, wxSafeConvertMB2WX(uts.nodename), sz - 1);
buf[sz] = wxT('\0');
wxStrlcpy(buf, wxSafeConvertMB2WX(uts.nodename), sz);
}
#elif defined(HAVE_GETHOSTNAME)
char cbuf[sz];
bool ok = gethostname(cbuf, sz) != -1;
if ( ok )
{
wxStrncpy(buf, wxSafeConvertMB2WX(cbuf), sz - 1);
buf[sz] = wxT('\0');
wxStrlcpy(buf, wxSafeConvertMB2WX(cbuf), sz);
}
#else // no uname, no gethostname
wxFAIL_MSG(wxT("don't know host name for this machine"));
@@ -839,7 +837,7 @@ bool wxGetFullHostName(wxChar *buf, int sz)
else
{
// the canonical name
wxStrncpy(buf, wxSafeConvertMB2WX(host->h_name), sz);
wxStrlcpy(buf, wxSafeConvertMB2WX(host->h_name), sz);
}
}
//else: it's already a FQDN (BSD behaves this way)
@@ -855,7 +853,7 @@ bool wxGetUserId(wxChar *buf, int sz)
*buf = wxT('\0');
if ((who = getpwuid(getuid ())) != NULL)
{
wxStrncpy (buf, wxSafeConvertMB2WX(who->pw_name), sz - 1);
wxStrlcpy (buf, wxSafeConvertMB2WX(who->pw_name), sz);
return true;
}
@@ -873,7 +871,7 @@ bool wxGetUserName(wxChar *buf, int sz)
char *comma = strchr(who->pw_gecos, ',');
if (comma)
*comma = '\0'; // cut off non-name comment fields
wxStrncpy (buf, wxSafeConvertMB2WX(who->pw_gecos), sz - 1);
wxStrlcpy(buf, wxSafeConvertMB2WX(who->pw_gecos), sz);
return true;
}