Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 26 additions & 14 deletions js/src/builtin/String.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1172,16 +1172,11 @@ static size_t ToLowerCaseLength(const char16_t* chars, size_t startIndex,
}

template <typename CharT>
static JSLinearString* ToLowerCase(JSContext* cx, JSLinearString* str) {
static JSLinearString* ToLowerCaseInternal(JSContext* cx, JSLinearString* str) {
// Unlike toUpperCase, toLowerCase has the nice invariant that if the
// input is a Latin-1 string, the output is also a Latin-1 string.

StringChars<CharT> newChars(cx);
// Foxhound: cache the taint up here to prevent GC issues
SafeStringTaint taint(str->taint());
if (taint.hasTaint()) {
taint.extend(TaintOperationFromContextJSString(cx, "toLowerCase", str));
}

const size_t length = str->length();
size_t resultLength;
Expand Down Expand Up @@ -1234,11 +1229,7 @@ static JSLinearString* ToLowerCase(JSContext* cx, JSLinearString* str) {
}

// If no character needs to change, return the input string.
// Foxhound: disabled. We need to return a new string here (so we can correctly
// set the taint). However, we are in an AutoCheckCannotGC block, so cannot
// allocate a new string here.
if (i == length) {
str->setTaint(cx, taint);
return str;
}

Expand Down Expand Up @@ -1269,15 +1260,28 @@ static JSLinearString* ToLowerCase(JSContext* cx, JSLinearString* str) {
}
}

// Foxhound: Add taint operation to all taint ranges of the input string.
JSLinearString* res = newChars.template toStringDontDeflate<CanGC>(cx, resultLength);
if (res && taint.hasTaint()) {
res->setTaint(cx, taint);
}

return res;
}

template <typename CharT>
static JSLinearString* ToLowerCase(JSContext* cx, JSLinearString* str) {
JSLinearString* res = ToLowerCaseInternal<CharT>(cx, str);
if (res && str->isTainted()) {
if (res == str) {
res = NewDependentString(cx, str, 0, str->length());
if (!res) {
return nullptr;
}
}
SafeStringTaint taint(str->taint());
taint.extend(TaintOperationFromContextJSString(cx, "toLowerCase", str));
res->setTaint(taint);
}
return res;
}

JSLinearString* js::StringToLowerCase(JSContext* cx, JSString* string) {
JSLinearString* linear = string->ensureLinear(cx);
if (!linear) {
Expand Down Expand Up @@ -1939,6 +1943,14 @@ static bool str_normalize(JSContext* cx, unsigned argc, Value* vp) {
return false;
}

if (str->isTainted()) {
JSString* dep = NewDependentString(cx, str, 0, str->length());
if (!dep) {
return false;
}
str = dep;
}

using NormalizationForm = mozilla::intl::String::NormalizationForm;

NormalizationForm form;
Expand Down
2 changes: 2 additions & 0 deletions taint/test/mochitest/mochitest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,5 @@ scheme = https
[test_network_request_url_argument.html]
[test_string_iterator.html]
[test_json_stringify.html]
[test_toLowerCase.html]
[test_normalize.html]
28 changes: 28 additions & 0 deletions taint/test/mochitest/test_normalize.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>
Test normalize (see
https://github.com/SAP/project-foxhound/issues/361)
</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css" />

<script type="text/javascript">
function test(str) {
const s = String.tainted(str);
const t = s.normalize();
SimpleTest.is(s.taint[0].flow.length, 1);
SimpleTest.is(t.taint[0].flow.length, 2);
}

add_task(async function test_normalize() {
test("hello");
test("\u0041\u006d\u00e9\u006c\u0069\u0065");
});
</script>
</head>

<body></body>
</html>
28 changes: 28 additions & 0 deletions taint/test/mochitest/test_toLowerCase.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>
Test toLowerCase (see
https://github.com/SAP/project-foxhound/issues/361)
</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css" />

<script type="text/javascript">
function test(str) {
const s = String.tainted(str);
const t = s.toLowerCase();
SimpleTest.is(s.taint[0].flow.length, 1);
SimpleTest.is(t.taint[0].flow.length, 2);
}

add_task(async function test_toLowerCase() {
test("hello");
test("HELLO");
});
</script>
</head>

<body></body>
</html>
Loading