From f00204d341eeb409a9808b0674e7949cbe240a65 Mon Sep 17 00:00:00 2001 From: Francesco Montorsi Date: Wed, 14 Jan 2009 19:26:14 +0000 Subject: [PATCH] use wxStrnlen() and add NULL-checks in wxMsgCatalogFile::FillHash for safer handling of corrupted MO files (closes #3151) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@58106 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- samples/internat/internat.cpp | 3 ++- src/common/intl.cpp | 30 +++++++++++++++++++++++------- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/samples/internat/internat.cpp b/samples/internat/internat.cpp index 77d62a296d..8bf6bd55e1 100644 --- a/samples/internat/internat.cpp +++ b/samples/internat/internat.cpp @@ -234,7 +234,8 @@ bool MyApp::OnInit() wxLocale::AddCatalogLookupPathPrefix(wxT(".")); // Initialize the catalogs we'll be using - m_locale.AddCatalog(wxT("internat")); + if (!m_locale.AddCatalog(wxT("internat"))) + wxLogError(_("Couldn't find/load the 'internat' catalog.")); // this catalog is installed in standard location on Linux systems and // shows that you may make use of the standard message catalogs as well diff --git a/src/common/intl.cpp b/src/common/intl.cpp index e20715c4c7..e242998a14 100644 --- a/src/common/intl.cpp +++ b/src/common/intl.cpp @@ -868,6 +868,9 @@ wxPluralFormsCalculator* wxPluralFormsCalculator::make(const char* s) // wxMsgCatalogFile corresponds to one disk-file message catalog. // // This is a "low-level" class and is used only by wxMsgCatalog +// NOTE: for the documentation of the binary catalog (.MO) files refer to +// the GNU gettext manual: +// http://www.gnu.org/software/autoconf/manual/gettext/MO-Files.html // ---------------------------------------------------------------------------- WX_DECLARE_EXPORTED_STRING_HASH_MAP(wxString, wxMessagesHash); @@ -881,12 +884,12 @@ public: // load the catalog from disk (szDirPrefix corresponds to language) bool Load(const wxString& szDirPrefix, const wxString& szName, - wxPluralFormsCalculatorPtr& rPluralFormsCalculator); + wxPluralFormsCalculatorPtr& rPluralFormsCalculator); // fills the hash with string-translation pairs - void FillHash(wxMessagesHash& hash, - const wxString& msgIdCharset, - bool convertEncoding) const; + bool FillHash(wxMessagesHash& hash, + const wxString& msgIdCharset, + bool convertEncoding) const; // return the charset of the strings in this catalog or empty string if // none/unknown @@ -1356,7 +1359,7 @@ bool wxMsgCatalogFile::Load(const wxString& szDirPrefix, const wxString& szName, return true; } -void wxMsgCatalogFile::FillHash(wxMessagesHash& hash, +bool wxMsgCatalogFile::FillHash(wxMessagesHash& hash, const wxString& msgIdCharset, bool convertEncoding) const { @@ -1444,6 +1447,8 @@ void wxMsgCatalogFile::FillHash(wxMessagesHash& hash, for (size_t32 i = 0; i < m_numStrings; i++) { const char *data = StringAtOfs(m_pOrigTable, i); + if (!data) + return false; // may happen for invalid MO files wxString msgid; #if wxUSE_UNICODE @@ -1458,6 +1463,9 @@ void wxMsgCatalogFile::FillHash(wxMessagesHash& hash, #endif // wxUSE_UNICODE data = StringAtOfs(m_pTransTable, i); + if (!data) + return false; // may happen for invalid MO files + size_t length = Swap(m_pTransTable[i].nLen); size_t offset = 0; size_t index = 0; @@ -1488,7 +1496,12 @@ void wxMsgCatalogFile::FillHash(wxMessagesHash& hash, } // skip this string - offset += strlen(str) + 1; + // IMPORTANT: accesses to the 'data' pointer are valid only for + // the first 'length+1' bytes (GNU specs says that the + // final NUL is not counted in length); using wxStrnlen() + // we make sure we don't access memory beyond the valid range + // (which otherwise may happen for invalid MO files): + offset += wxStrnlen(str, length - offset) + 1; ++index; } } @@ -1497,6 +1510,8 @@ void wxMsgCatalogFile::FillHash(wxMessagesHash& hash, delete sourceConv; delete inputConvPtr; #endif // wxUSE_WCHAR_T + + return true; } @@ -1531,7 +1546,8 @@ bool wxMsgCatalog::Load(const wxString& dirPrefix, const wxString& name, if ( !file.Load(dirPrefix, name, m_pluralFormsCalculator) ) return false; - file.FillHash(m_messages, msgIdCharset, bConvertEncoding); + if ( !file.FillHash(m_messages, msgIdCharset, bConvertEncoding) ) + return false; #if !wxUSE_UNICODE // we should use a conversion compatible with the message catalog encoding