diff --git a/js/src/builtin/String.cpp b/js/src/builtin/String.cpp index 9e36292907e99..76281990745d9 100644 --- a/js/src/builtin/String.cpp +++ b/js/src/builtin/String.cpp @@ -1172,16 +1172,11 @@ static size_t ToLowerCaseLength(const char16_t* chars, size_t startIndex, } template -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 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; @@ -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; } @@ -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(cx, resultLength); - if (res && taint.hasTaint()) { - res->setTaint(cx, taint); - } return res; } +template +static JSLinearString* ToLowerCase(JSContext* cx, JSLinearString* str) { + JSLinearString* res = ToLowerCaseInternal(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) { @@ -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; diff --git a/taint/test/mochitest/mochitest.ini b/taint/test/mochitest/mochitest.ini index a6989309fd508..90b0ac76a8306 100644 --- a/taint/test/mochitest/mochitest.ini +++ b/taint/test/mochitest/mochitest.ini @@ -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] diff --git a/taint/test/mochitest/test_normalize.html b/taint/test/mochitest/test_normalize.html new file mode 100644 index 0000000000000..0f8ea6d69401a --- /dev/null +++ b/taint/test/mochitest/test_normalize.html @@ -0,0 +1,28 @@ + + + + + + Test normalize (see + https://github.com/SAP/project-foxhound/issues/361) + + + + + + + + + diff --git a/taint/test/mochitest/test_toLowerCase.html b/taint/test/mochitest/test_toLowerCase.html new file mode 100644 index 0000000000000..cf8fd475bd429 --- /dev/null +++ b/taint/test/mochitest/test_toLowerCase.html @@ -0,0 +1,28 @@ + + + + + + Test toLowerCase (see + https://github.com/SAP/project-foxhound/issues/361) + + + + + + + + +