Bug 1032511 - URLSearchParam should decode any non-unicode input correctly, r=hsivonen

This commit is contained in:
Andrea Marchesini 2014-08-07 17:45:14 -07:00
parent a0cb588368
commit 326492814b
4 changed files with 98 additions and 10 deletions

View File

@ -5,6 +5,7 @@
#include "URLSearchParams.h"
#include "mozilla/dom/URLSearchParamsBinding.h"
#include "mozilla/dom/EncodingUtils.h"
namespace mozilla {
namespace dom {
@ -98,30 +99,31 @@ URLSearchParams::ParseInput(const nsACString& aInput,
name.Assign(string);
}
nsAutoCString decodedName;
nsAutoString decodedName;
DecodeString(name, decodedName);
nsAutoCString decodedValue;
nsAutoString decodedValue;
DecodeString(value, decodedValue);
AppendInternal(NS_ConvertUTF8toUTF16(decodedName),
NS_ConvertUTF8toUTF16(decodedValue));
AppendInternal(decodedName, decodedValue);
}
NotifyObservers(aObserver);
}
void
URLSearchParams::DecodeString(const nsACString& aInput, nsACString& aOutput)
URLSearchParams::DecodeString(const nsACString& aInput, nsAString& aOutput)
{
nsACString::const_iterator start, end;
aInput.BeginReading(start);
aInput.EndReading(end);
nsCString unescaped;
while (start != end) {
// replace '+' with U+0020
if (*start == '+') {
aOutput.Append(' ');
unescaped.Append(' ');
++start;
continue;
}
@ -148,20 +150,62 @@ URLSearchParams::DecodeString(const nsACString& aInput, nsACString& aOutput)
if (first != end && second != end &&
ASCII_HEX_DIGIT(*first) && ASCII_HEX_DIGIT(*second)) {
aOutput.Append(HEX_DIGIT(first) * 16 + HEX_DIGIT(second));
unescaped.Append(HEX_DIGIT(first) * 16 + HEX_DIGIT(second));
start = ++second;
continue;
} else {
aOutput.Append('%');
unescaped.Append('%');
++start;
continue;
}
}
aOutput.Append(*start);
unescaped.Append(*start);
++start;
}
ConvertString(unescaped, aOutput);
}
void
URLSearchParams::ConvertString(const nsACString& aInput, nsAString& aOutput)
{
aOutput.Truncate();
if (!mDecoder) {
mDecoder = EncodingUtils::DecoderForEncoding("UTF-8");
if (!mDecoder) {
MOZ_ASSERT(mDecoder, "Failed to create a decoder.");
return;
}
}
nsACString::const_iterator iter;
aInput.BeginReading(iter);
int32_t inputLength = aInput.Length();
int32_t outputLength = 0;
nsresult rv = mDecoder->GetMaxLength(iter.get(), inputLength,
&outputLength);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
const mozilla::fallible_t fallible = mozilla::fallible_t();
nsAutoArrayPtr<char16_t> buf(new (fallible) char16_t[outputLength + 1]);
if (!buf) {
return;
}
rv = mDecoder->Convert(iter.get(), &inputLength, buf, &outputLength);
if (NS_SUCCEEDED(rv)) {
buf[outputLength] = 0;
if (!aOutput.Assign(buf, outputLength, mozilla::fallible_t())) {
aOutput.Truncate();
}
}
}
/* static */ PLDHashOperator

View File

@ -13,6 +13,7 @@
#include "nsClassHashtable.h"
#include "nsHashKeys.h"
#include "nsISupports.h"
#include "nsIUnicodeDecoder.h"
namespace mozilla {
namespace dom {
@ -83,7 +84,8 @@ private:
void DeleteAll();
void DecodeString(const nsACString& aInput, nsACString& aOutput);
void DecodeString(const nsACString& aInput, nsAString& aOutput);
void ConvertString(const nsACString& aInput, nsAString& aOutput);
void NotifyObservers(URLSearchParamsObserver* aExceptObserver);
@ -98,6 +100,7 @@ private:
nsClassHashtable<nsStringHashKey, nsTArray<nsString>> mSearchParams;
nsTArray<nsRefPtr<URLSearchParamsObserver>> mObservers;
nsCOMPtr<nsIUnicodeDecoder> mDecoder;
};
} // namespace dom

View File

@ -74,6 +74,7 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop spec
[test_url_malformedHost.html]
[test_urlExceptions.html]
[test_urlSearchParams.html]
[test_urlSearchParams_utf8.html]
[test_urlutils_stringify.html]
[test_window_constructor.html]
[test_window_cross_origin_props.html]

View File

@ -0,0 +1,40 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1032511
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1032511</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1032511">Mozilla Bug 1032511</a>
<p id="display"></p>
<div id="content" style="display: none">
<iframe name="x" id="x"></iframe>
<iframe name="y" id="y"></iframe>
</div>
<pre id="test">
</pre>
<a href="http://www.example.net?a=b&c=d" id="anchor">foobar</a>
<area href="http://www.example.net?a=b&c=d" id="area">foobar</area>
<script type="application/javascript">
/** Test for Bug 1032511 **/
var a = new URLSearchParams("%e2");
ok(a, "a exists");
is(a.toString(), '=', "The value should be here.");
a = new URLSearchParams("a%e2");
// This is a known decoder bug that fails to emit a REPLACEMENT CHARACTER.
is(a.toString(), 'a=', "The value should be here.");
a = new URLSearchParams("a%e2b");
is(a.toString(), 'a%EF%BF%BDb=', "The value should be here.");
</script>
</body>
</html>