From 0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 03:47:29 +0200 Subject: Adding upstream version 115.8.0esr. Signed-off-by: Daniel Baumann --- mfbt/tests/gtest/TestTainting.cpp | 485 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 485 insertions(+) create mode 100644 mfbt/tests/gtest/TestTainting.cpp (limited to 'mfbt/tests/gtest/TestTainting.cpp') diff --git a/mfbt/tests/gtest/TestTainting.cpp b/mfbt/tests/gtest/TestTainting.cpp new file mode 100644 index 0000000000..0025819c06 --- /dev/null +++ b/mfbt/tests/gtest/TestTainting.cpp @@ -0,0 +1,485 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "gtest/gtest.h" +#include + +#include "mozilla/Array.h" +#include "mozilla/Assertions.h" +#include "mozilla/Range.h" +#include "mozilla/Tainting.h" +#include "nsTHashtable.h" +#include "nsHashKeys.h" +#include "nsTArray.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using mozilla::Tainted; + +#define EXPECTED_INT 10 +#define EXPECTED_CHAR 'z' + +static bool externalFunction(int arg) { return arg > 2; } + +// ================================================================== +// MOZ_VALIDATE_AND_GET ============================================= +TEST(Tainting, moz_validate_and_get) +{ + int bar; + int comparisonVariable = 20; + Tainted foo = Tainted(EXPECTED_INT); + + bar = MOZ_VALIDATE_AND_GET(foo, foo < 20); + ASSERT_EQ(bar, EXPECTED_INT); + + // This test is for comparison to an external variable, testing the + // default capture mode of the lambda used inside the macro. + bar = MOZ_VALIDATE_AND_GET(foo, foo < comparisonVariable); + ASSERT_EQ(bar, EXPECTED_INT); + + bar = MOZ_VALIDATE_AND_GET( + foo, foo < 20, + "foo must be less than 20 because higher values represent decibel" + "levels greater than a a jet engine inside your ear."); + ASSERT_EQ(bar, EXPECTED_INT); + + // Test an external variable with a comment. + bar = MOZ_VALIDATE_AND_GET(foo, foo < comparisonVariable, "Test comment"); + ASSERT_EQ(bar, EXPECTED_INT); + + // Test an external function with a comment. + bar = MOZ_VALIDATE_AND_GET(foo, externalFunction(foo), "Test comment"); + ASSERT_EQ(bar, EXPECTED_INT); + + // Lambda Tests + bar = + MOZ_VALIDATE_AND_GET(foo, ([&foo]() { return externalFunction(foo); }())); + ASSERT_EQ(bar, EXPECTED_INT); + + // This test is for the lambda variant with a supplied assertion + // string. + bar = + MOZ_VALIDATE_AND_GET(foo, ([&foo]() { return externalFunction(foo); }()), + "This tests a comment"); + ASSERT_EQ(bar, EXPECTED_INT); + + // This test is for the lambda variant with a captured variable + bar = MOZ_VALIDATE_AND_GET(foo, ([&foo, &comparisonVariable] { + bool intermediateResult = externalFunction(foo); + return intermediateResult || + comparisonVariable < 4; + }()), + "This tests a comment"); + ASSERT_EQ(bar, EXPECTED_INT); + + // This test is for the lambda variant with full capture mode + bar = MOZ_VALIDATE_AND_GET(foo, ([&] { + bool intermediateResult = externalFunction(foo); + return intermediateResult || + comparisonVariable < 4; + }()), + "This tests a comment"); + ASSERT_EQ(bar, EXPECTED_INT); + + // External lambdas + auto lambda1 = [](int foo) { return externalFunction(foo); }; + + auto lambda2 = [&](int foo) { + bool intermediateResult = externalFunction(foo); + return intermediateResult || comparisonVariable < 4; + }; + + // Test with an explicit capture + auto lambda3 = [&comparisonVariable](int foo) { + bool intermediateResult = externalFunction(foo); + return intermediateResult || comparisonVariable < 4; + }; + + bar = MOZ_VALIDATE_AND_GET(foo, lambda1(foo)); + ASSERT_EQ(bar, EXPECTED_INT); + + // Test with a comment + bar = MOZ_VALIDATE_AND_GET(foo, lambda1(foo), "Test comment."); + ASSERT_EQ(bar, EXPECTED_INT); + + // Test with a default capture mode + bar = MOZ_VALIDATE_AND_GET(foo, lambda2(foo), "Test comment."); + ASSERT_EQ(bar, EXPECTED_INT); + + bar = MOZ_VALIDATE_AND_GET(foo, lambda3(foo), "Test comment."); + ASSERT_EQ(bar, EXPECTED_INT); + + // We can't test MOZ_VALIDATE_AND_GET failing, because that triggers + // a release assert. +} + +// ================================================================== +// MOZ_IS_VALID ===================================================== +TEST(Tainting, moz_is_valid) +{ + int comparisonVariable = 20; + Tainted foo = Tainted(EXPECTED_INT); + + ASSERT_TRUE(MOZ_IS_VALID(foo, foo < 20)); + + ASSERT_FALSE(MOZ_IS_VALID(foo, foo > 20)); + + ASSERT_TRUE(MOZ_IS_VALID(foo, foo < comparisonVariable)); + + ASSERT_TRUE( + MOZ_IS_VALID(foo, ([&foo]() { return externalFunction(foo); }()))); + + ASSERT_TRUE(MOZ_IS_VALID(foo, ([&foo, &comparisonVariable]() { + bool intermediateResult = externalFunction(foo); + return intermediateResult || + comparisonVariable < 4; + }()))); + + // External lambdas + auto lambda1 = [](int foo) { return externalFunction(foo); }; + + auto lambda2 = [&](int foo) { + bool intermediateResult = externalFunction(foo); + return intermediateResult || comparisonVariable < 4; + }; + + // Test with an explicit capture + auto lambda3 = [&comparisonVariable](int foo) { + bool intermediateResult = externalFunction(foo); + return intermediateResult || comparisonVariable < 4; + }; + + ASSERT_TRUE(MOZ_IS_VALID(foo, lambda1(foo))); + + ASSERT_TRUE(MOZ_IS_VALID(foo, lambda2(foo))); + + ASSERT_TRUE(MOZ_IS_VALID(foo, lambda3(foo))); +} + +// ================================================================== +// MOZ_VALIDATE_OR ================================================== +TEST(Tainting, moz_validate_or) +{ + int result; + int comparisonVariable = 20; + Tainted foo = Tainted(EXPECTED_INT); + + result = MOZ_VALIDATE_OR(foo, foo < 20, 100); + ASSERT_EQ(result, EXPECTED_INT); + + result = MOZ_VALIDATE_OR(foo, foo > 20, 100); + ASSERT_EQ(result, 100); + + result = MOZ_VALIDATE_OR(foo, foo < comparisonVariable, 100); + ASSERT_EQ(result, EXPECTED_INT); + + // External lambdas + auto lambda1 = [](int foo) { return externalFunction(foo); }; + + auto lambda2 = [&](int foo) { + bool intermediateResult = externalFunction(foo); + return intermediateResult || comparisonVariable < 4; + }; + + // Test with an explicit capture + auto lambda3 = [&comparisonVariable](int foo) { + bool intermediateResult = externalFunction(foo); + return intermediateResult || comparisonVariable < 4; + }; + + result = MOZ_VALIDATE_OR(foo, lambda1(foo), 100); + ASSERT_EQ(result, EXPECTED_INT); + + result = MOZ_VALIDATE_OR(foo, lambda2(foo), 100); + ASSERT_EQ(result, EXPECTED_INT); + + result = MOZ_VALIDATE_OR(foo, lambda3(foo), 100); + ASSERT_EQ(result, EXPECTED_INT); + + result = + MOZ_VALIDATE_OR(foo, ([&foo]() { return externalFunction(foo); }()), 100); + ASSERT_EQ(result, EXPECTED_INT); + + // This test is for the lambda variant with a supplied assertion + // string. + result = + MOZ_VALIDATE_OR(foo, ([&foo] { return externalFunction(foo); }()), 100); + ASSERT_EQ(result, EXPECTED_INT); + + // This test is for the lambda variant with a captured variable + result = + MOZ_VALIDATE_OR(foo, ([&foo, &comparisonVariable] { + bool intermediateResult = externalFunction(foo); + return intermediateResult || comparisonVariable < 4; + }()), + 100); + ASSERT_EQ(result, EXPECTED_INT); + + // This test is for the lambda variant with full capture mode + result = + MOZ_VALIDATE_OR(foo, ([&] { + bool intermediateResult = externalFunction(foo); + return intermediateResult || comparisonVariable < 4; + }()), + 100); + ASSERT_EQ(result, EXPECTED_INT); +} + +// ================================================================== +// MOZ_FIND_AND_VALIDATE ============================================ +TEST(Tainting, moz_find_and_validate) +{ + Tainted foo = Tainted(EXPECTED_INT); + Tainted baz = Tainted(EXPECTED_CHAR); + + //------------------------------- + const mozilla::Array mozarrayWithFoo(0, 5, EXPECTED_INT, 15, 20, 25); + const mozilla::Array mozarrayWithoutFoo(0, 5, 15, 20, 25); + + ASSERT_TRUE(*MOZ_FIND_AND_VALIDATE(foo, list_item == foo, mozarrayWithFoo) == + mozarrayWithFoo[2]); + + ASSERT_TRUE(MOZ_FIND_AND_VALIDATE(foo, list_item == foo, + mozarrayWithoutFoo) == nullptr); + + //------------------------------- + class TestClass { + public: + int a; + int b; + + TestClass(int a, int b) { + this->a = a; + this->b = b; + } + + bool operator==(const TestClass& other) const { + return this->a == other.a && this->b == other.b; + } + }; + + const mozilla::Array mozarrayOfClassesWithFoo( + TestClass(0, 1), TestClass(2, 3), TestClass(EXPECTED_INT, EXPECTED_INT), + TestClass(4, 5), TestClass(6, 7)); + + ASSERT_TRUE(*MOZ_FIND_AND_VALIDATE( + foo, foo == list_item.a && foo == list_item.b, + mozarrayOfClassesWithFoo) == mozarrayOfClassesWithFoo[2]); + + ASSERT_TRUE(*MOZ_FIND_AND_VALIDATE( + foo, (foo == list_item.a && foo == list_item.b), + mozarrayOfClassesWithFoo) == mozarrayOfClassesWithFoo[2]); + + ASSERT_TRUE( + *MOZ_FIND_AND_VALIDATE( + foo, + (foo == list_item.a && foo == list_item.b && externalFunction(foo)), + mozarrayOfClassesWithFoo) == mozarrayOfClassesWithFoo[2]); + + ASSERT_TRUE(*MOZ_FIND_AND_VALIDATE( + foo, ([](int tainted_val, TestClass list_item) { + return tainted_val == list_item.a && + tainted_val == list_item.b; + }(foo, list_item)), + mozarrayOfClassesWithFoo) == mozarrayOfClassesWithFoo[2]); + + auto lambda4 = [](int tainted_val, TestClass list_item) { + return tainted_val == list_item.a && tainted_val == list_item.b; + }; + + ASSERT_TRUE(*MOZ_FIND_AND_VALIDATE(foo, lambda4(foo, list_item), + mozarrayOfClassesWithFoo) == + mozarrayOfClassesWithFoo[2]); + + //------------------------------- + const char m[] = "m"; + const char o[] = "o"; + const char z[] = {EXPECTED_CHAR, '\0'}; + const char l[] = "l"; + const char a[] = "a"; + + nsTHashtable hashtableWithBaz; + hashtableWithBaz.PutEntry(m); + hashtableWithBaz.PutEntry(o); + hashtableWithBaz.PutEntry(z); + hashtableWithBaz.PutEntry(l); + hashtableWithBaz.PutEntry(a); + nsTHashtable hashtableWithoutBaz; + hashtableWithoutBaz.PutEntry(m); + hashtableWithoutBaz.PutEntry(o); + hashtableWithoutBaz.PutEntry(l); + hashtableWithoutBaz.PutEntry(a); + + ASSERT_TRUE(MOZ_FIND_AND_VALIDATE(baz, *list_item.GetKey() == baz, + hashtableWithBaz) == + hashtableWithBaz.GetEntry(z)); + + ASSERT_TRUE(MOZ_FIND_AND_VALIDATE(baz, *list_item.GetKey() == baz, + hashtableWithoutBaz) == nullptr); + + //------------------------------- + const nsTArray nsTArrayWithFoo = {0, 5, EXPECTED_INT, 15, 20, 25}; + const nsTArray nsTArrayWithoutFoo = {0, 5, 15, 20, 25}; + + ASSERT_TRUE(*MOZ_FIND_AND_VALIDATE(foo, list_item == foo, nsTArrayWithFoo) == + nsTArrayWithFoo[2]); + + ASSERT_TRUE(MOZ_FIND_AND_VALIDATE(foo, list_item == foo, + nsTArrayWithoutFoo) == nullptr); + + //------------------------------- + const std::array arrayWithFoo{0, 5, EXPECTED_INT, 15, 20, 25}; + const std::array arrayWithoutFoo{0, 5, 15, 20, 25}; + + ASSERT_TRUE(*MOZ_FIND_AND_VALIDATE(foo, list_item == foo, arrayWithFoo) == + arrayWithFoo[2]); + + ASSERT_TRUE(MOZ_FIND_AND_VALIDATE(foo, list_item == foo, arrayWithoutFoo) == + nullptr); + + //------------------------------- + const std::deque dequeWithFoo{0, 5, EXPECTED_INT, 15, 20, 25}; + const std::deque dequeWithoutFoo{0, 5, 15, 20, 25}; + + ASSERT_TRUE(*MOZ_FIND_AND_VALIDATE(foo, list_item == foo, dequeWithFoo) == + dequeWithFoo[2]); + + ASSERT_TRUE(MOZ_FIND_AND_VALIDATE(foo, list_item == foo, dequeWithoutFoo) == + nullptr); + + //------------------------------- + const std::forward_list forwardWithFoo{0, 5, EXPECTED_INT, 15, 20, 25}; + const std::forward_list forwardWithoutFoo{0, 5, 15, 20, 25}; + + auto forwardListIt = forwardWithFoo.begin(); + std::advance(forwardListIt, 2); + + ASSERT_TRUE(*MOZ_FIND_AND_VALIDATE(foo, list_item == foo, forwardWithFoo) == + *forwardListIt); + + ASSERT_TRUE(MOZ_FIND_AND_VALIDATE(foo, list_item == foo, forwardWithoutFoo) == + nullptr); + + //------------------------------- + const std::list listWithFoo{0, 5, EXPECTED_INT, 15, 20, 25}; + const std::list listWithoutFoo{0, 5, 15, 20, 25}; + + auto listIt = listWithFoo.begin(); + std::advance(listIt, 2); + + ASSERT_TRUE(*MOZ_FIND_AND_VALIDATE(foo, list_item == foo, listWithFoo) == + *listIt); + + ASSERT_TRUE(MOZ_FIND_AND_VALIDATE(foo, list_item == foo, listWithoutFoo) == + nullptr); + + //------------------------------- + const std::map mapWithFoo{{ + {"zero", 0}, + {"five", 5}, + {"ten", EXPECTED_INT}, + {"fifteen", 15}, + {"twenty", 20}, + {"twenty-five", 25}, + }}; + const std::map mapWithoutFoo{{ + {"zero", 0}, + {"five", 5}, + {"fifteen", 15}, + {"twenty", 20}, + {"twenty-five", 25}, + }}; + + const auto map_it = mapWithFoo.find("ten"); + + ASSERT_TRUE( + MOZ_FIND_AND_VALIDATE(foo, list_item.second == foo, mapWithFoo)->second == + map_it->second); + + ASSERT_TRUE(MOZ_FIND_AND_VALIDATE(foo, list_item.second == foo, + mapWithoutFoo) == nullptr); + + //------------------------------- + const std::set setWithFoo{0, 5, EXPECTED_INT, 15, 20, 25}; + const std::set setWithoutFoo{0, 5, 15, 20, 25}; + + auto setIt = setWithFoo.find(EXPECTED_INT); + + ASSERT_TRUE(*MOZ_FIND_AND_VALIDATE(foo, list_item == foo, setWithFoo) == + *setIt); + + ASSERT_TRUE(MOZ_FIND_AND_VALIDATE(foo, list_item == foo, setWithoutFoo) == + nullptr); + + //------------------------------- + const std::unordered_map unordermapWithFoo = { + {"zero", 0}, {"five", 5}, {"ten", EXPECTED_INT}, + {"fifteen", 15}, {"twenty", 20}, {"twenty-five", 25}, + }; + const std::unordered_map unordermapWithoutFoo{{ + {"zero", 0}, + {"five", 5}, + {"fifteen", 15}, + {"twenty", 20}, + {"twenty-five", 25}, + }}; + + auto unorderedMapIt = unordermapWithFoo.find("ten"); + + ASSERT_TRUE( + MOZ_FIND_AND_VALIDATE(foo, list_item.second == foo, unordermapWithFoo) + ->second == unorderedMapIt->second); + + ASSERT_TRUE(MOZ_FIND_AND_VALIDATE(foo, list_item.second == foo, + unordermapWithoutFoo) == nullptr); + + //------------------------------- + const std::unordered_set unorderedsetWithFoo{0, 5, EXPECTED_INT, + 15, 20, 25}; + const std::unordered_set unorderedsetWithoutFoo{0, 5, 15, 20, 25}; + + auto unorderedSetIt = unorderedsetWithFoo.find(EXPECTED_INT); + + ASSERT_TRUE(*MOZ_FIND_AND_VALIDATE(foo, list_item == foo, + unorderedsetWithFoo) == *unorderedSetIt); + + ASSERT_TRUE(MOZ_FIND_AND_VALIDATE(foo, list_item == foo, + unorderedsetWithoutFoo) == nullptr); + + //------------------------------- + const std::vector vectorWithFoo{0, 5, EXPECTED_INT, 15, 20, 25}; + const std::vector vectorWithoutFoo{0, 5, 15, 20, 25}; + + ASSERT_TRUE(*MOZ_FIND_AND_VALIDATE(foo, list_item == foo, vectorWithFoo) == + vectorWithFoo[2]); + + ASSERT_TRUE(MOZ_FIND_AND_VALIDATE(foo, list_item == foo, vectorWithoutFoo) == + nullptr); +} + +// ================================================================== +// MOZ_NO_VALIDATE ================================================== +TEST(Tainting, moz_no_validate) +{ + int result; + Tainted foo = Tainted(EXPECTED_INT); + + result = MOZ_NO_VALIDATE( + foo, + "Value is used to match against a dictionary key in the parent." + "If there's no key present, there won't be a match." + "There is no risk of grabbing a cross-origin value from the dictionary," + "because the IPC actor is instatiated per-content-process and the " + "dictionary is not shared between actors."); + ASSERT_TRUE(result == EXPECTED_INT); +} -- cgit v1.2.3