diff options
author | Eike Rathke <erack@redhat.com> | 2013-02-13 21:49:52 +0100 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2013-02-15 13:57:27 +0100 |
commit | cf8318429e3177574f9d60042c402401f484bf17 (patch) | |
tree | 4fe007544c1c3bf02ca703d4cfaca26f0cd250ea /sal | |
parent | 8a07032d01aa59fd94c393669d8ac4b8443acb2b (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
Diffstat (limited to 'sal')
-rw-r--r-- | sal/osl/w32/nlsupport.c | 39 |
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"" ); } |