Bug Block some Mac charsets. Patch by Simon Montagu <smontagu@smontagu.org>, backport by Mike Hommey<mh+mozilla@glandium.org>, r=emk, sr=dveditz, a1.9.0.next=dveditz

git-svn-id: svn://10.0.0.236/trunk@261973 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
alqahira%ardisson.org 2011-02-28 05:56:38 +00:00
parent 93f3a66ef6
commit 6da90a22a8
13 changed files with 182 additions and 12 deletions

View File

@ -113,10 +113,11 @@ interface nsICharsetConverterManager : nsISupports
* character encoding may be used for certain purposes, if it is
* multi-byte, and the language code for it. See charsetData.properties
* for the source of this data. Some known property names:
* notForBrowser - not to be used in the bowser.
* notForBrowser - not to be used in the browser.
* notForOutgoing - not to be used for exporting files.
* LangGroup - language code for charset, e.g. 'he' and 'zh-CN'.
* isMultibyte - is this a multi-byte charset?
* isXSSVulnerable - not to be used in untrusted web content
*
* @param charset name of the character encoding, e.g. 'iso-8859-15'.
* @param prop property desired for the character encoding.
@ -135,3 +136,16 @@ interface nsICharsetConverterManager : nsISupports
nsIAtom getCharsetLangGroup(in string charset);
nsIAtom getCharsetLangGroupRaw(in string charset);
};
[scriptable, uuid(36982132-707c-4d77-b27f-958e76e022de)]
interface nsICharsetConverterManager_1_9_BRANCH : nsICharsetConverterManager
{
/**
* "Internal" versions of getUnicodeDecoder* will return a decoder for any
* charset; the other versions will return NS_ERROR_UCONV_NOCONV if the
* requested charset is vulnerable to XSS attacks and should not be used
* with untrusted input
*/
nsIUnicodeDecoder getUnicodeDecoderInternal(in string charset);
nsIUnicodeDecoder getUnicodeDecoderRawInternal(in string charset);
};

View File

@ -102,3 +102,16 @@ interface nsIScriptableUnicodeConverter : nsISupports
*/
attribute string charset;
};
[scriptable, uuid(f7ed6618-5ff5-4f0b-bb83-48ce63eb289b)]
interface nsIScriptableUnicodeConverter_1_9_BRANCH : nsIScriptableUnicodeConverter
{
/**
* Internal use
*
* When this attribute is set, all charsets may be accessed.
* When it is not set (the default), charsets with the isXSSVulnerable flag
* may not be accessed
*/
attribute boolean isInternal;
};

View File

@ -47,6 +47,10 @@
## charset_name.notForOutgoing = anything - specifies that this charset is
## not to be used for exporting files ('SaveAsCharset' in composer)
##
## charset_name.isXSSVulnerable = anything - specifies that this charset is
## known to be vulnerable to XSS attacks and should not be exposed to web
## content
##
## charset_name.LangGroup =
##
## charset_name.isMultibyte = multi byte charsets
@ -67,6 +71,13 @@ ibm1131.notForBrowser = true
x-ibm1046.notForBrowser = true
iso-8859-8-e.notForBrowser = true
utf-7.notForBrowser = true
x-mac-arabic.notForBrowser = true
x-mac-farsi.notForBrowser = true
x-mac-hebrew.notForBrowser = true
x-mac-arabic.isXSSVulnerable = true
x-mac-farsi.isXSSVulnerable = true
x-mac-hebrew.isXSSVulnerable = true
t.61-8bit.notForOutgoing = true
utf-7.notForOutgoing = true

View File

@ -69,8 +69,9 @@
// Class nsCharsetConverterManager [implementation]
NS_IMPL_THREADSAFE_ISUPPORTS1(nsCharsetConverterManager,
nsICharsetConverterManager)
NS_IMPL_THREADSAFE_ISUPPORTS2(nsCharsetConverterManager,
nsICharsetConverterManager,
nsICharsetConverterManager_1_9_BRANCH)
nsCharsetConverterManager::nsCharsetConverterManager()
:mDataBundle(NULL), mTitleBundle(NULL)
@ -222,6 +223,20 @@ nsCharsetConverterManager::GetUnicodeEncoderRaw(const char * aDest,
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
nsCharsetConverterManager::GetUnicodeDecoder(const char * aSrc,
nsIUnicodeDecoder ** aResult)
@ -237,8 +252,22 @@ nsCharsetConverterManager::GetUnicodeDecoder(const char * aSrc,
}
NS_IMETHODIMP
nsCharsetConverterManager::GetUnicodeDecoderRaw(const char * aSrc,
nsIUnicodeDecoder ** aResult)
nsCharsetConverterManager::GetUnicodeDecoderInternal(const char * aSrc,
nsIUnicodeDecoder ** aResult)
{
// resolve the charset first
nsCAutoString charset;
// fully qualify to possibly avoid vtable call
nsCharsetConverterManager::GetCharsetAlias(aSrc, charset);
return nsCharsetConverterManager::GetUnicodeDecoderRawInternal(charset.get(),
aResult);
}
NS_IMETHODIMP
nsCharsetConverterManager::GetUnicodeDecoderRawInternal(const char * aSrc,
nsIUnicodeDecoder ** aResult)
{
*aResult= nsnull;
nsCOMPtr<nsIUnicodeDecoder> decoder;

View File

@ -46,10 +46,11 @@
#include "nsINativeUConvService.h"
#endif
class nsCharsetConverterManager : public nsICharsetConverterManager
class nsCharsetConverterManager : public nsICharsetConverterManager_1_9_BRANCH
{
NS_DECL_ISUPPORTS
NS_DECL_NSICHARSETCONVERTERMANAGER
NS_DECL_NSICHARSETCONVERTERMANAGER_1_9_BRANCH
public:

View File

@ -52,9 +52,12 @@
static PRInt32 gInstanceCount = 0;
/* Implementation file */
NS_IMPL_ISUPPORTS1(nsScriptableUnicodeConverter, nsIScriptableUnicodeConverter)
NS_IMPL_ISUPPORTS2(nsScriptableUnicodeConverter,
nsIScriptableUnicodeConverter,
nsIScriptableUnicodeConverter_1_9_BRANCH)
nsScriptableUnicodeConverter::nsScriptableUnicodeConverter()
: mIsInternal(PR_FALSE)
{
PR_AtomicIncrement(&gInstanceCount);
}
@ -270,13 +273,27 @@ nsScriptableUnicodeConverter::SetCharset(const char * aCharset)
return InitConverter();
}
NS_IMETHODIMP
nsScriptableUnicodeConverter::GetIsInternal(PRBool *aIsInternal)
{
*aIsInternal = mIsInternal;
return NS_OK;
}
NS_IMETHODIMP
nsScriptableUnicodeConverter::SetIsInternal(const PRBool aIsInternal)
{
mIsInternal = aIsInternal;
return NS_OK;
}
nsresult
nsScriptableUnicodeConverter::InitConverter()
{
nsresult rv = NS_OK;
mEncoder = NULL ;
nsCOMPtr<nsICharsetConverterManager> ccm = do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
nsCOMPtr<nsICharsetConverterManager_1_9_BRANCH> ccm = do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
if (NS_SUCCEEDED( rv) && (nsnull != ccm)) {
// get charset atom due to getting unicode converter
@ -286,7 +303,11 @@ nsScriptableUnicodeConverter::InitConverter()
if(NS_SUCCEEDED(rv)) {
rv = mEncoder->SetOutputErrorBehavior(nsIUnicodeEncoder::kOnError_Replace, nsnull, (PRUnichar)'?');
if(NS_SUCCEEDED(rv)) {
rv = ccm->GetUnicodeDecoder(mCharset.get(), getter_AddRefs(mDecoder));
rv = mIsInternal ?
ccm->GetUnicodeDecoderInternal(mCharset.get(),
getter_AddRefs(mDecoder)) :
ccm->GetUnicodeDecoder(mCharset.get(),
getter_AddRefs(mDecoder));
}
}
}

View File

@ -44,11 +44,12 @@
#include "nsICharsetConverterManager.h"
#include "nsIScriptableUConv.h"
class nsScriptableUnicodeConverter : public nsIScriptableUnicodeConverter
class nsScriptableUnicodeConverter : public nsIScriptableUnicodeConverter_1_9_BRANCH
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISCRIPTABLEUNICODECONVERTER
NS_DECL_NSISCRIPTABLEUNICODECONVERTER_1_9_BRANCH
nsScriptableUnicodeConverter();
virtual ~nsScriptableUnicodeConverter();
@ -59,6 +60,7 @@ protected:
nsCAutoString mCharset;
nsCOMPtr<nsIUnicodeEncoder> mEncoder;
nsCOMPtr<nsIUnicodeDecoder> mDecoder;
PRPackedBool mIsInternal;
nsresult FinishWithLength(char **_retval, PRInt32* aLength);
nsresult ConvertFromUnicodeWithLength(const nsAString& aSrc,

View File

@ -0,0 +1,52 @@
const Ci = Components.interfaces;
const Cc = Components.classes;
const CC = Components.Constructor;
// Tests whether characters above 0x7F decode to ASCII characters liable to
// expose XSS vulnerabilities
function run_test() {
var failures = false;
var ccManager = Cc["@mozilla.org/charset-converter-manager;1"]
.getService(Ci.nsICharsetConverterManager);
var ScriptableUnicodeConverter =
CC("@mozilla.org/intl/scriptableunicodeconverter",
"nsIScriptableUnicodeConverter");
var decodingConverter = new ScriptableUnicodeConverter();
var charsetList = ccManager.getDecoderList();
var counter = 0;
while (charsetList.hasMore()) {
++counter;
var charset = charsetList.getNext();
dump("testing " + counter + " " + charset + "\n");
try {
decodingConverter.charset = charset;
} catch(e) {
dump("Warning: couldn't set decoder charset to " + charset + "\n");
continue;
}
for (var i = 0x80; i < 0x100; ++i) {
var inString = String.fromCharCode(i);
var outString;
try {
outString = decodingConverter.ConvertToUnicode(inString) +
decodingConverter.Finish();
} catch(e) {
outString = String.fromCharCode(0xFFFD);
}
for (var n = 0; n < outString.length; ++n) {
var outChar = outString.charAt(n);
if (outChar == '<' || outChar == '>' || outChar == '/') {
dump(charset + " has a problem: " + escape(inString) +
" decodes to '" + outString + "'\n");
failures = true;
}
}
}
}
if (failures) {
do_throw("test failed\n");
}
}

View File

@ -0,0 +1,7 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Testcase for bug 603423</title>
</head>
<body><p><iframe src="data:text/html;charset=iso-8859-1,<p lang=%22en-US%22 style=%22font-family: serif%22>Hello World</p>"</iframe></p></body>
</html>

View File

@ -0,0 +1,7 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Testcase for bug 603423</title>
</head>
<body><p lang="en-US"><iframe src="data:text/html;charset=x-mac-arabic,<p lang=%22en-US%22 style=%22font-family: serif%22>Hello World</p>"</iframe></p></body>
</html>

View File

@ -847,3 +847,4 @@ fails-if(MOZ_WIDGET_TOOLKIT=="gtk2") == 424074-1-ref2.xul 424074-1-ref3.xul
== 486848-1.xul 486848-1-ref.xul
== 487539-1.html about:blank
== 488390-1.html 488390-1-ref.html
== 603423-1.html 603423-1-ref.html

View File

@ -187,14 +187,22 @@ nsresult nsScanner::SetDocumentCharset(const nsACString& aCharset , PRInt32 aSou
nsIUnicodeDecoder * decoder = nsnull;
res = nsParser::GetCharsetConverterManager()->
GetUnicodeDecoderRaw(mCharset.get(), &decoder);
GetUnicodeDecoderRaw(mCharset.get(), &decoder);
if (NS_FAILED(res))
{
// GetUnicodeDecoderRaw can fail if the charset has the .isXSSVulnerable
// flag. Try to fallback to ISO-8859-1
mCharset.AssignLiteral("ISO-8859-1");
mCharsetSource = kCharsetFromWeakDocTypeDefault;
res = nsParser::GetCharsetConverterManager()->
GetUnicodeDecoderRaw(mCharset.get(), &decoder);
}
if(NS_SUCCEEDED(res) && (nsnull != decoder))
{
NS_IF_RELEASE(mUnicodeDecoder);
mUnicodeDecoder = decoder;
}
return res;
}

View File

@ -1252,6 +1252,10 @@ nsresult nsCharsetMenu::InitMoreSubmenus(nsCStringArray& aDecs)
NS_TIMELINE_START_TIMER("nsCharsetMenu::InitMoreSubmenus");
nsresult res = NS_OK;
// remove charsets "not for browser"
res = RemoveFlaggedCharsets(aDecs, NS_LITERAL_STRING(".notForBrowser"));
if (NS_FAILED(res)) return res;
nsCOMPtr<nsIRDFContainer> container1;
nsCOMPtr<nsIRDFContainer> container2;