Bug 710693 - Move internal encoding check into nsCharsetAlias. r=smontagu

This commit is contained in:
Masatoshi Kimura 2012-05-24 18:45:10 -04:00
Родитель 0e9dd95906
Коммит 4c63cc5246
10 изменённых файлов: 133 добавлений и 99 удалений

Просмотреть файл

@ -1753,7 +1753,7 @@ gfxFontUtils::DecodeFontName(const PRUint8 *aNameData, PRInt32 aByteLen,
} }
nsCOMPtr<nsIUnicodeDecoder> decoder; nsCOMPtr<nsIUnicodeDecoder> decoder;
rv = ccm->GetUnicodeDecoderRawInternal(csName, getter_AddRefs(decoder)); rv = ccm->GetUnicodeDecoderRaw(csName, getter_AddRefs(decoder));
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
NS_WARNING("failed to get the decoder for a font name string"); NS_WARNING("failed to get the decoder for a font name string");
return false; return false;

Просмотреть файл

@ -39,6 +39,7 @@ LOCAL_INCLUDES = \
-I$(srcdir)/../strres/src \ -I$(srcdir)/../strres/src \
-I$(srcdir)/../locale/src \ -I$(srcdir)/../locale/src \
-I$(srcdir)/../locale/src/$(LOCALE_DIR) \ -I$(srcdir)/../locale/src/$(LOCALE_DIR) \
-I$(srcdir)/../uconv/src \
$(NULL) $(NULL)
SHARED_LIBRARY_LIBS = \ SHARED_LIBRARY_LIBS = \

Просмотреть файл

@ -28,6 +28,9 @@
// locale // locale
#include "nsLocaleConstructors.h" #include "nsLocaleConstructors.h"
// uconv
#include "nsCharsetConverterManager.h"
NS_GENERIC_FACTORY_CONSTRUCTOR(nsJISx4051LineBreaker) NS_GENERIC_FACTORY_CONSTRUCTOR(nsJISx4051LineBreaker)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSampleWordBreaker) NS_GENERIC_FACTORY_CONSTRUCTOR(nsSampleWordBreaker)
@ -148,10 +151,20 @@ static const mozilla::Module::ContractIDEntry kIntlContracts[] = {
{ NULL } { NULL }
}; };
static void
I18nModuleDtor()
{
nsCharsetConverterManager::Shutdown();
}
static const mozilla::Module kIntlModule = { static const mozilla::Module kIntlModule = {
mozilla::Module::kVersion, mozilla::Module::kVersion,
kIntlCIDs, kIntlCIDs,
kIntlContracts, kIntlContracts,
NULL,
NULL,
NULL,
I18nModuleDtor
}; };
NSMODULE_DEFN(nsI18nModule) = &kIntlModule; NSMODULE_DEFN(nsI18nModule) = &kIntlModule;

Просмотреть файл

@ -9,8 +9,12 @@
#include "nscore.h" #include "nscore.h"
#include "nsStringGlue.h" #include "nsStringGlue.h"
class nsCharsetConverterManager;
class nsCharsetAlias class nsCharsetAlias
{ {
friend class nsCharsetConverterManager;
static nsresult GetPreferredInternal(const nsACString& aAlias, nsACString& aResult);
public: public:
static nsresult GetPreferred(const nsACString& aAlias, nsACString& aResult); static nsresult GetPreferred(const nsACString& aAlias, nsACString& aResult);
static nsresult Equals(const nsACString& aCharset1, const nsACString& aCharset2, bool* aResult); static nsresult Equals(const nsACString& aCharset1, const nsACString& aCharset2, bool* aResult);

Просмотреть файл

@ -55,6 +55,10 @@ EXTRA_JS_MODULES = \
# we don't want the shared lib, but we want to force the creation of a static lib. # we don't want the shared lib, but we want to force the creation of a static lib.
FORCE_STATIC_LIB = 1 FORCE_STATIC_LIB = 1
LOCAL_INCLUDES = \
-I$(topsrcdir)/intl/uconv/src \
$(NULL)
include $(topsrcdir)/config/rules.mk include $(topsrcdir)/config/rules.mk
nsCharsetAlias.$(OBJ_SUFFIX): charsetalias.properties.h nsCharsetAlias.$(OBJ_SUFFIX): charsetalias.properties.h

Просмотреть файл

@ -8,6 +8,10 @@
#include "nsCharsetAlias.h" #include "nsCharsetAlias.h"
#include "pratom.h" #include "pratom.h"
// for NS_ERROR_UCONV_NOCONV
#include "nsEncoderDecoderUtils.h"
#include "nsCharsetConverterManager.h"
// for NS_IMPL_IDS only // for NS_IMPL_IDS only
#include "nsIPlatformCharset.h" #include "nsIPlatformCharset.h"
@ -25,11 +29,9 @@ static const char* kAliases[][3] = {
//-------------------------------------------------------------- //--------------------------------------------------------------
// static // static
nsresult nsresult
nsCharsetAlias::GetPreferred(const nsACString& aAlias, nsCharsetAlias::GetPreferredInternal(const nsACString& aAlias,
nsACString& oResult) nsACString& oResult)
{ {
if (aAlias.IsEmpty()) return NS_ERROR_NULL_POINTER;
nsCAutoString key(aAlias); nsCAutoString key(aAlias);
ToLowerCase(key); ToLowerCase(key);
@ -37,6 +39,24 @@ nsCharsetAlias::GetPreferred(const nsACString& aAlias,
ArrayLength(kAliases), key, oResult); ArrayLength(kAliases), key, oResult);
} }
//--------------------------------------------------------------
// static
nsresult
nsCharsetAlias::GetPreferred(const nsACString& aAlias,
nsACString& oResult)
{
if (aAlias.IsEmpty()) return NS_ERROR_NULL_POINTER;
nsresult res = GetPreferredInternal(aAlias, oResult);
if (NS_FAILED(res))
return res;
if (nsCharsetConverterManager::IsInternal(oResult))
return NS_ERROR_UCONV_NOCONV;
return res;
}
//-------------------------------------------------------------- //--------------------------------------------------------------
// static // static
nsresult nsresult
@ -57,12 +77,12 @@ nsCharsetAlias::Equals(const nsACString& aCharset1,
*oResult = false; *oResult = false;
nsCAutoString name1; nsCAutoString name1;
res = GetPreferred(aCharset1, name1); res = GetPreferredInternal(aCharset1, name1);
if (NS_FAILED(res)) if (NS_FAILED(res))
return res; return res;
nsCAutoString name2; nsCAutoString name2;
res = GetPreferred(aCharset2, name2); res = GetPreferredInternal(aCharset2, name2);
if (NS_FAILED(res)) if (NS_FAILED(res))
return res; return res;

Просмотреть файл

@ -33,20 +33,16 @@ interface nsIUTF8StringEnumerator;
* @created 21/Feb/2000 * @created 21/Feb/2000
* @author Catalin Rotaru [CATA] * @author Catalin Rotaru [CATA]
*/ */
[scriptable, uuid(bf733b00-198f-4553-a061-637a21793330)] [scriptable, uuid(a0550d46-8d9c-47dd-acc7-c083620dff12)]
interface nsICharsetConverterManager : nsISupports interface nsICharsetConverterManager : nsISupports
{ {
/** /**
* Get the Unicode decoder for the given charset. * Get the Unicode decoder for the given charset.
* The "Raw" version skips charset alias resolution * The "Raw" version skips charset alias resolution
* The "Internal" version will return a decoder for any charset; the others
* will return NS_ERROR_UCONV_NOCONV if the requested charsets is
* vulnerable to XSS attacks and should not be used with untrusted input
*/ */
[noscript] nsIUnicodeDecoder getUnicodeDecoder(in string charset); [noscript] nsIUnicodeDecoder getUnicodeDecoder(in string charset);
[noscript] nsIUnicodeDecoder getUnicodeDecoderRaw(in string charset); [noscript] nsIUnicodeDecoder getUnicodeDecoderRaw(in string charset);
[noscript] nsIUnicodeDecoder getUnicodeDecoderInternal(in string charset); [noscript] nsIUnicodeDecoder getUnicodeDecoderInternal(in string charset);
[noscript] nsIUnicodeDecoder getUnicodeDecoderRawInternal(in string charset);
/** /**
* Get the Unicode encoder for the given charset. * Get the Unicode encoder for the given charset.

Просмотреть файл

@ -27,26 +27,32 @@
// just for CONTRACTIDs // just for CONTRACTIDs
#include "nsCharsetConverterManager.h" #include "nsCharsetConverterManager.h"
static nsIStringBundle * sDataBundle;
static nsIStringBundle * sTitleBundle;
// Class nsCharsetConverterManager [implementation] // Class nsCharsetConverterManager [implementation]
NS_IMPL_THREADSAFE_ISUPPORTS1(nsCharsetConverterManager, NS_IMPL_THREADSAFE_ISUPPORTS1(nsCharsetConverterManager,
nsICharsetConverterManager) nsICharsetConverterManager)
nsCharsetConverterManager::nsCharsetConverterManager() nsCharsetConverterManager::nsCharsetConverterManager()
: mDataBundle(NULL)
, mTitleBundle(NULL)
{ {
} }
nsCharsetConverterManager::~nsCharsetConverterManager() nsCharsetConverterManager::~nsCharsetConverterManager()
{ {
NS_IF_RELEASE(mDataBundle);
NS_IF_RELEASE(mTitleBundle);
} }
nsresult nsCharsetConverterManager::LoadExtensibleBundle( //static
const char* aCategory, void nsCharsetConverterManager::Shutdown()
nsIStringBundle ** aResult) {
NS_IF_RELEASE(sDataBundle);
NS_IF_RELEASE(sTitleBundle);
}
static
nsresult LoadExtensibleBundle(const char* aCategory,
nsIStringBundle ** aResult)
{ {
nsCOMPtr<nsIStringBundleService> sbServ = nsCOMPtr<nsIStringBundleService> sbServ =
mozilla::services::GetStringBundleService(); mozilla::services::GetStringBundleService();
@ -56,10 +62,11 @@ nsresult nsCharsetConverterManager::LoadExtensibleBundle(
return sbServ->CreateExtensibleBundle(aCategory, aResult); return sbServ->CreateExtensibleBundle(aCategory, aResult);
} }
nsresult nsCharsetConverterManager::GetBundleValue(nsIStringBundle * aBundle, static
const char * aName, nsresult GetBundleValue(nsIStringBundle * aBundle,
const nsAFlatString& aProp, const char * aName,
PRUnichar ** aResult) const nsAFlatString& aProp,
PRUnichar ** aResult)
{ {
nsAutoString key; nsAutoString key;
@ -70,10 +77,11 @@ nsresult nsCharsetConverterManager::GetBundleValue(nsIStringBundle * aBundle,
return aBundle->GetStringFromName(key.get(), aResult); return aBundle->GetStringFromName(key.get(), aResult);
} }
nsresult nsCharsetConverterManager::GetBundleValue(nsIStringBundle * aBundle, static
const char * aName, nsresult GetBundleValue(nsIStringBundle * aBundle,
const nsAFlatString& aProp, const char * aName,
nsAString& aResult) const nsAFlatString& aProp,
nsAString& aResult)
{ {
nsresult rv = NS_OK; nsresult rv = NS_OK;
@ -87,6 +95,35 @@ nsresult nsCharsetConverterManager::GetBundleValue(nsIStringBundle * aBundle,
return NS_OK; return NS_OK;
} }
static
nsresult GetCharsetDataImpl(const char * aCharset, const PRUnichar * aProp,
nsAString& aResult)
{
if (aCharset == NULL)
return NS_ERROR_NULL_POINTER;
// aProp can be NULL
if (sDataBundle == NULL) {
nsresult rv = LoadExtensibleBundle(NS_DATA_BUNDLE_CATEGORY, &sDataBundle);
if (NS_FAILED(rv))
return rv;
}
return GetBundleValue(sDataBundle, aCharset, nsDependentString(aProp), aResult);
}
//static
bool nsCharsetConverterManager::IsInternal(const nsACString& aCharset)
{
nsAutoString str;
// fully qualify to possibly avoid vtable call
nsresult rv = GetCharsetDataImpl(PromiseFlatCString(aCharset).get(),
NS_LITERAL_STRING(".isXSSVulnerable").get(),
str);
return NS_SUCCEEDED(rv);
}
//----------------------------------------------------------------------------//---------------------------------------------------------------------------- //----------------------------------------------------------------------------//----------------------------------------------------------------------------
// Interface nsICharsetConverterManager [implementation] // Interface nsICharsetConverterManager [implementation]
@ -132,29 +169,17 @@ nsCharsetConverterManager::GetUnicodeEncoderRaw(const char * aDest,
return rv; return rv;
} }
NS_IMETHODIMP
nsCharsetConverterManager::GetUnicodeDecoderRaw(const char * aSrc,
nsIUnicodeDecoder ** aResult)
{
nsresult rv;
nsAutoString str;
rv = GetCharsetData(aSrc, NS_LITERAL_STRING(".isXSSVulnerable").get(), str);
if (NS_SUCCEEDED(rv))
return NS_ERROR_UCONV_NOCONV;
return GetUnicodeDecoderRawInternal(aSrc, aResult);
}
NS_IMETHODIMP NS_IMETHODIMP
nsCharsetConverterManager::GetUnicodeDecoder(const char * aSrc, nsCharsetConverterManager::GetUnicodeDecoder(const char * aSrc,
nsIUnicodeDecoder ** aResult) nsIUnicodeDecoder ** aResult)
{ {
// resolve the charset first // resolve the charset first
nsCAutoString charset; nsCAutoString charset;
// fully qualify to possibly avoid vtable call // fully qualify to possibly avoid vtable call
nsCharsetConverterManager::GetCharsetAlias(aSrc, charset); nsresult rv = nsCharsetConverterManager::GetCharsetAlias(aSrc, charset);
if (NS_FAILED(rv))
return rv;
return nsCharsetConverterManager::GetUnicodeDecoderRaw(charset.get(), return nsCharsetConverterManager::GetUnicodeDecoderRaw(charset.get(),
aResult); aResult);
@ -166,18 +191,18 @@ nsCharsetConverterManager::GetUnicodeDecoderInternal(const char * aSrc,
{ {
// resolve the charset first // resolve the charset first
nsCAutoString charset; nsCAutoString charset;
// fully qualify to possibly avoid vtable call nsresult rv = nsCharsetAlias::GetPreferredInternal(nsDependentCString(aSrc),
nsresult rv = nsCharsetConverterManager::GetCharsetAlias(aSrc, charset); charset);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
return nsCharsetConverterManager::GetUnicodeDecoderRawInternal(charset.get(), return nsCharsetConverterManager::GetUnicodeDecoderRaw(charset.get(),
aResult); aResult);
} }
NS_IMETHODIMP NS_IMETHODIMP
nsCharsetConverterManager::GetUnicodeDecoderRawInternal(const char * aSrc, nsCharsetConverterManager::GetUnicodeDecoderRaw(const char * aSrc,
nsIUnicodeDecoder ** aResult) nsIUnicodeDecoder ** aResult)
{ {
*aResult= nsnull; *aResult= nsnull;
nsCOMPtr<nsIUnicodeDecoder> decoder; nsCOMPtr<nsIUnicodeDecoder> decoder;
@ -186,7 +211,7 @@ nsCharsetConverterManager::GetUnicodeDecoderRawInternal(const char * aSrc,
NS_NAMED_LITERAL_CSTRING(contractbase, NS_UNICODEDECODER_CONTRACTID_BASE); NS_NAMED_LITERAL_CSTRING(contractbase, NS_UNICODEDECODER_CONTRACTID_BASE);
nsDependentCString src(aSrc); nsDependentCString src(aSrc);
decoder = do_CreateInstance(PromiseFlatCString(contractbase + src).get(), decoder = do_CreateInstance(PromiseFlatCString(contractbase + src).get(),
&rv); &rv);
NS_ENSURE_SUCCESS(rv, NS_ERROR_UCONV_NOCONV); NS_ENSURE_SUCCESS(rv, NS_ERROR_UCONV_NOCONV);
@ -195,10 +220,10 @@ nsCharsetConverterManager::GetUnicodeDecoderRawInternal(const char * aSrc,
return rv; return rv;
} }
nsresult static
nsCharsetConverterManager::GetList(const nsACString& aCategory, nsresult GetList(const nsACString& aCategory,
const nsACString& aPrefix, const nsACString& aPrefix,
nsIUTF8StringEnumerator** aResult) nsIUTF8StringEnumerator** aResult)
{ {
if (aResult == NULL) if (aResult == NULL)
return NS_ERROR_NULL_POINTER; return NS_ERROR_NULL_POINTER;
@ -289,12 +314,12 @@ nsCharsetConverterManager::GetCharsetTitle(const char * aCharset,
{ {
NS_ENSURE_ARG_POINTER(aCharset); NS_ENSURE_ARG_POINTER(aCharset);
if (mTitleBundle == NULL) { if (sTitleBundle == NULL) {
nsresult rv = LoadExtensibleBundle(NS_TITLE_BUNDLE_CATEGORY, &mTitleBundle); nsresult rv = LoadExtensibleBundle(NS_TITLE_BUNDLE_CATEGORY, &sTitleBundle);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
return GetBundleValue(mTitleBundle, aCharset, NS_LITERAL_STRING(".title"), aResult); return GetBundleValue(sTitleBundle, aCharset, NS_LITERAL_STRING(".title"), aResult);
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -302,17 +327,7 @@ nsCharsetConverterManager::GetCharsetData(const char * aCharset,
const PRUnichar * aProp, const PRUnichar * aProp,
nsAString& aResult) nsAString& aResult)
{ {
if (aCharset == NULL) return GetCharsetDataImpl(aCharset, aProp, aResult);
return NS_ERROR_NULL_POINTER;
// aProp can be NULL
if (mDataBundle == NULL) {
nsresult rv = LoadExtensibleBundle(NS_DATA_BUNDLE_CATEGORY, &mDataBundle);
if (NS_FAILED(rv))
return rv;
}
return GetBundleValue(mDataBundle, aCharset, nsDependentString(aProp), aResult);
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -336,19 +351,10 @@ nsCharsetConverterManager::GetCharsetLangGroupRaw(const char * aCharset,
{ {
*aResult = nsnull; *aResult = nsnull;
if (aCharset == NULL)
return NS_ERROR_NULL_POINTER;
nsresult rv = NS_OK;
if (mDataBundle == NULL) {
rv = LoadExtensibleBundle(NS_DATA_BUNDLE_CATEGORY, &mDataBundle);
if (NS_FAILED(rv))
return rv;
}
nsAutoString langGroup; nsAutoString langGroup;
rv = GetBundleValue(mDataBundle, aCharset, NS_LITERAL_STRING(".LangGroup"), langGroup); // fully qualify to possibly avoid vtable call
nsresult rv = nsCharsetConverterManager::GetCharsetData(
aCharset, NS_LITERAL_STRING(".LangGroup").get(), langGroup);
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
ToLowerCase(langGroup); // use lowercase for all language atoms ToLowerCase(langGroup); // use lowercase for all language atoms

Просмотреть файл

@ -11,34 +11,24 @@
#include "nsInterfaceHashtable.h" #include "nsInterfaceHashtable.h"
#include "mozilla/Mutex.h" #include "mozilla/Mutex.h"
class nsCharsetAlias;
class nsCharsetConverterManager : public nsICharsetConverterManager class nsCharsetConverterManager : public nsICharsetConverterManager
{ {
friend class nsCharsetAlias;
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
NS_DECL_NSICHARSETCONVERTERMANAGER NS_DECL_NSICHARSETCONVERTERMANAGER
public: public:
nsCharsetConverterManager(); nsCharsetConverterManager();
virtual ~nsCharsetConverterManager(); virtual ~nsCharsetConverterManager();
static void Shutdown();
private: private:
nsIStringBundle * mDataBundle; static bool IsInternal(const nsACString& aCharset);
nsIStringBundle * mTitleBundle;
nsresult LoadExtensibleBundle(const char * aRegistryKey,
nsIStringBundle ** aResult);
nsresult GetBundleValue(nsIStringBundle * aBundle,
const char * aName,
const nsAFlatString& aProp, PRUnichar ** aResult);
nsresult GetBundleValue(nsIStringBundle * aBundle,
const char * aName,
const nsAFlatString& aProp, nsAString& aResult);
nsresult GetList(const nsACString& aCategory,
const nsACString& aPrefix,
nsIUTF8StringEnumerator** aResult);
}; };
#endif // nsCharsetConverterManager_h__ #endif // nsCharsetConverterManager_h__

Просмотреть файл

@ -9,7 +9,7 @@ function run_test()
while (decoderList.hasMore()) { while (decoderList.hasMore()) {
var decoder = decoderList.getNext(); var decoder = decoderList.getNext();
try { try {
var langGroup = ccManager.getCharsetLangGroup(decoder); var langGroup = ccManager.getCharsetLangGroupRaw(decoder);
} catch(e) { } catch(e) {
dump("no langGroup for " + decoder + "\n"); dump("no langGroup for " + decoder + "\n");
failures = true; failures = true;