X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e5cf63c9a8661dfe10ded99bdcfd20076cea7d49..b53aea81d2e102224b452ef5bf7aee1132f37c6f:/src/common/intl.cpp diff --git a/src/common/intl.cpp b/src/common/intl.cpp index e20715c4c7..d0a11eac2f 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 @@ -1304,59 +1307,63 @@ bool wxMsgCatalogFile::Load(const wxString& szDirPrefix, const wxString& szName, // plural forms formula from it: const char* headerData = StringAtOfs(m_pOrigTable, 0); - if (headerData && headerData[0] == 0) + if ( headerData && headerData[0] == '\0' ) { // Extract the charset: - wxString header = wxString::FromAscii(StringAtOfs(m_pTransTable, 0)); - int begin = header.Find(wxS("Content-Type: text/plain; charset=")); - if (begin != wxNOT_FOUND) + const char * const header = StringAtOfs(m_pTransTable, 0); + const char * + cset = strstr(header, "Content-Type: text/plain; charset="); + if ( cset ) { - begin += 34; //strlen("Content-Type: text/plain; charset=") - size_t end = header.find('\n', begin); - if (end != size_t(-1)) + cset += 34; // strlen("Content-Type: text/plain; charset=") + + const char * const csetEnd = strchr(cset, '\n'); + if ( csetEnd ) { - m_charset.assign(header, begin, end - begin); - if (m_charset == wxS("CHARSET")) + m_charset = wxString(cset, csetEnd - cset); + if ( m_charset == wxS("CHARSET") ) { // "CHARSET" is not valid charset, but lazy translator - m_charset.Clear(); + m_charset.empty(); } } } // else: incorrectly filled Content-Type header // Extract plural forms: - begin = header.Find(wxS("Plural-Forms:")); - if (begin != wxNOT_FOUND) + const char * plurals = strstr(header, "Plural-Forms:"); + if ( plurals ) { - begin += 13; - size_t end = header.find('\n', begin); - if (end != size_t(-1)) + plurals += 13; // strlen("Plural-Forms:") + const char * const pluralsEnd = strchr(plurals, '\n'); + if ( pluralsEnd ) { - wxString pfs(header, begin, end - begin); - wxPluralFormsCalculator* pCalculator = wxPluralFormsCalculator - ::make(pfs.ToAscii()); - if (pCalculator != 0) + const size_t pluralsLen = pluralsEnd - plurals; + wxCharBuffer buf(pluralsLen); + strncpy(buf.data(), plurals, pluralsLen); + wxPluralFormsCalculator * const + pCalculator = wxPluralFormsCalculator::make(buf); + if ( pCalculator ) { rPluralFormsCalculator.reset(pCalculator); } else { - wxLogVerbose(_("Cannot parse Plural-Forms:'%s'"), pfs.c_str()); + wxLogVerbose(_("Failed to parse Plural-Forms: '%s'"), + buf.data()); } } } - if (rPluralFormsCalculator.get() == NULL) - { + + if ( !rPluralFormsCalculator.get() ) rPluralFormsCalculator.reset(wxPluralFormsCalculator::make()); - } } // everything is fine return true; } -void wxMsgCatalogFile::FillHash(wxMessagesHash& hash, +bool wxMsgCatalogFile::FillHash(wxMessagesHash& hash, const wxString& msgIdCharset, bool convertEncoding) const { @@ -1444,6 +1451,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 +1467,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 +1500,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 +1514,8 @@ void wxMsgCatalogFile::FillHash(wxMessagesHash& hash, delete sourceConv; delete inputConvPtr; #endif // wxUSE_WCHAR_T + + return true; } @@ -1531,7 +1550,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 @@ -2180,7 +2200,7 @@ wxString wxLocale::GetSystemEncodingName() // the environment variables (in most cases this won't work, but I was // out of ideas) char *lang = getenv( "LC_ALL"); - char *dot = lang ? strchr(lang, '.') : (char *)NULL; + char *dot = lang ? strchr(lang, '.') : NULL; if (!dot) { lang = getenv( "LC_CTYPE" );