summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2013-02-13 21:49:52 +0100
committerEike Rathke <erack@redhat.com>2013-02-15 13:57:27 +0100
commitcf8318429e3177574f9d60042c402401f484bf17 (patch)
tree4fe007544c1c3bf02ca703d4cfaca26f0cd250ea
parent8a07032d01aa59fd94c393669d8ac4b8443acb2b (diff)
prevent out-of-bounds buffer writes in EnumLocalesParams
osl_getTextEncodingFromLocale() In case of the Language code being longer than 2 characters the string written to the struct EnumLocalesParams member was not 0-terminated if a Country code was also given (consecutive fields in the struct) unless the struct was packed in 4-byte alignment and luckily contained a 0 as the 4th byte. The locale could not had been matched in these cases. In case of a sufficiently long language or country argument the entire EnumLocalesParams struct could had been overflown. Change-Id: I1ec67ad0b3d12b0fa944d7e759bb5cb701842e39
-rw-r--r--sal/osl/w32/nlsupport.c39
1 files changed, 27 insertions, 12 deletions
diff --git a/sal/osl/w32/nlsupport.c b/sal/osl/w32/nlsupport.c
index 19e2a3f307bf..e05e584f98cd 100644
--- a/sal/osl/w32/nlsupport.c
+++ b/sal/osl/w32/nlsupport.c
@@ -33,10 +33,24 @@
#include <osl/process.h>
#include <rtl/tencinfo.h>
+
+/* XXX NOTE:
+ * http://msdn.microsoft.com/en-us/library/windows/desktop/dd373848.aspx
+ * (retrieved 2013-02-13) has some weird description for the LOCALE_SISO*
+ * constants: "The maximum number of characters allowed for this string is
+ * nine, including a terminating null character." NINE?!? In ISO 639 and ISO
+ * 3166?
+ */
+#define ELP_LANGUAGE_FIELD_LENGTH 4
+#define ELP_COUNTRY_FIELD_LENGTH 3
+
+/** Struct used in EnumLocalesProcA() called via EnumSystemLocalesA() to obtain
+ available locales.
+*/
struct EnumLocalesParams
{
- WCHAR Language[3];
- WCHAR Country[3];
+ WCHAR Language[ELP_LANGUAGE_FIELD_LENGTH];
+ WCHAR Country[ELP_COUNTRY_FIELD_LENGTH];
LCID Locale;
};
@@ -58,7 +72,7 @@ BOOL CALLBACK EnumLocalesProcA( LPSTR lpLocaleStringA )
LCID localeId;
LPSTR pszEndA;
- WCHAR langCode[4];
+ WCHAR langCode[ELP_LANGUAGE_FIELD_LENGTH];
/* convert hex-string to LCID */
localeId = strtol( lpLocaleStringA, &pszEndA, 16 );
@@ -76,16 +90,17 @@ BOOL CALLBACK EnumLocalesProcA( LPSTR lpLocaleStringA )
an error under WinNT/2000 when called with an
unicode only lcid
*/
- if( GetLocaleInfo( localeId, LOCALE_SISO639LANGNAME , langCode, 4 ) )
+ if( GetLocaleInfo( localeId, LOCALE_SISO639LANGNAME , langCode, ELP_LANGUAGE_FIELD_LENGTH ) )
{
- WCHAR ctryCode[4];
+ WCHAR ctryCode[ELP_COUNTRY_FIELD_LENGTH];
/* continue if language code does not match */
if( 0 != wcscmp( langCode, params->Language ) )
return TRUE;
/* check if country code is set and equals the current locale */
- if( '\0' != params->Country[0] && GetLocaleInfo( localeId, LOCALE_SISO3166CTRYNAME , ctryCode, 4 ) )
+ if( '\0' != params->Country[0] && GetLocaleInfo( localeId,
+ LOCALE_SISO3166CTRYNAME , ctryCode, ELP_COUNTRY_FIELD_LENGTH ) )
{
/* save return value in TLS and break if found desired locale */
if( 0 == wcscmp( ctryCode, params->Country ) )
@@ -173,11 +188,11 @@ rtl_TextEncoding SAL_CALL osl_getTextEncodingFromLocale( rtl_Locale * pLocale )
osl_getProcessLocale( &pLocale );
/* copy in parameters to structure */
- if( pLocale && pLocale->Language )
+ if( pLocale && pLocale->Language && pLocale->Language->length < ELP_LANGUAGE_FIELD_LENGTH )
{
wcscpy( params.Language, pLocale->Language->buffer );
- if( pLocale->Country )
+ if( pLocale->Country && pLocale->Country->length < ELP_COUNTRY_FIELD_LENGTH )
wcscpy( params.Country, pLocale->Country->buffer );
/* save pointer to local structure in TLS */
@@ -199,8 +214,8 @@ rtl_TextEncoding SAL_CALL osl_getTextEncodingFromLocale( rtl_Locale * pLocale )
void _imp_getProcessLocale( rtl_Locale ** ppLocale )
{
- WCHAR langCode[4];
- WCHAR ctryCode[4];
+ WCHAR langCode[ELP_LANGUAGE_FIELD_LENGTH];
+ WCHAR ctryCode[ELP_COUNTRY_FIELD_LENGTH];
LCID localeId;
OSL_ASSERT( ppLocale );
@@ -209,8 +224,8 @@ void _imp_getProcessLocale( rtl_Locale ** ppLocale )
localeId = GetUserDefaultLCID();
/* call GetLocaleInfo to retrieve the iso codes */
- if( GetLocaleInfo( localeId, LOCALE_SISO639LANGNAME , langCode, 4 ) &&
- GetLocaleInfo( localeId, LOCALE_SISO3166CTRYNAME , ctryCode, 4 ) )
+ if( GetLocaleInfo( localeId, LOCALE_SISO639LANGNAME , langCode, ELP_LANGUAGE_FIELD_LENGTH ) &&
+ GetLocaleInfo( localeId, LOCALE_SISO3166CTRYNAME , ctryCode, ELP_COUNTRY_FIELD_LENGTH ) )
{
*ppLocale = rtl_locale_register( langCode, ctryCode, L"" );
}