tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestTainting.cpp (16705B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "gtest/gtest.h"
      8 #include <math.h>
      9 
     10 #include "mozilla/Array.h"
     11 #include "mozilla/Tainting.h"
     12 #include "nsTHashtable.h"
     13 #include "nsHashKeys.h"
     14 #include "nsTArray.h"
     15 #include <array>
     16 #include <deque>
     17 #include <forward_list>
     18 #include <list>
     19 #include <map>
     20 #include <set>
     21 #include <unordered_map>
     22 #include <unordered_set>
     23 #include <vector>
     24 
     25 using mozilla::Tainted;
     26 
     27 #define EXPECTED_INT 10
     28 #define EXPECTED_CHAR 'z'
     29 
     30 static bool externalFunction(int arg) { return arg > 2; }
     31 
     32 // ==================================================================
     33 // MOZ_VALIDATE_AND_GET =============================================
     34 TEST(Tainting, moz_validate_and_get)
     35 {
     36  int bar;
     37  int comparisonVariable = 20;
     38  Tainted<int> foo = Tainted<int>(EXPECTED_INT);
     39 
     40  bar = MOZ_VALIDATE_AND_GET(foo, foo < 20);
     41  ASSERT_EQ(bar, EXPECTED_INT);
     42 
     43  // This test is for comparison to an external variable, testing the
     44  // default capture mode of the lambda used inside the macro.
     45  bar = MOZ_VALIDATE_AND_GET(foo, foo < comparisonVariable);
     46  ASSERT_EQ(bar, EXPECTED_INT);
     47 
     48  bar = MOZ_VALIDATE_AND_GET(
     49      foo, foo < 20,
     50      "foo must be less than 20 because higher values represent decibel"
     51      "levels greater than a a jet engine inside your ear.");
     52  ASSERT_EQ(bar, EXPECTED_INT);
     53 
     54  // Test an external variable with a comment.
     55  bar = MOZ_VALIDATE_AND_GET(foo, foo < comparisonVariable, "Test comment");
     56  ASSERT_EQ(bar, EXPECTED_INT);
     57 
     58  // Test an external function with a comment.
     59  bar = MOZ_VALIDATE_AND_GET(foo, externalFunction(foo), "Test comment");
     60  ASSERT_EQ(bar, EXPECTED_INT);
     61 
     62  // Lambda Tests
     63  bar =
     64      MOZ_VALIDATE_AND_GET(foo, ([&foo]() { return externalFunction(foo); }()));
     65  ASSERT_EQ(bar, EXPECTED_INT);
     66 
     67  // This test is for the lambda variant with a supplied assertion
     68  // string.
     69  bar =
     70      MOZ_VALIDATE_AND_GET(foo, ([&foo]() { return externalFunction(foo); }()),
     71                           "This tests a comment");
     72  ASSERT_EQ(bar, EXPECTED_INT);
     73 
     74  // This test is for the lambda variant with a captured variable
     75  bar = MOZ_VALIDATE_AND_GET(foo, ([&foo, &comparisonVariable] {
     76                               bool intermediateResult = externalFunction(foo);
     77                               return intermediateResult ||
     78                                      comparisonVariable < 4;
     79                             }()),
     80                             "This tests a comment");
     81  ASSERT_EQ(bar, EXPECTED_INT);
     82 
     83  // This test is for the lambda variant with full capture mode
     84  bar = MOZ_VALIDATE_AND_GET(foo, ([&] {
     85                               bool intermediateResult = externalFunction(foo);
     86                               return intermediateResult ||
     87                                      comparisonVariable < 4;
     88                             }()),
     89                             "This tests a comment");
     90  ASSERT_EQ(bar, EXPECTED_INT);
     91 
     92  // External lambdas
     93  auto lambda1 = [](int foo) { return externalFunction(foo); };
     94 
     95  auto lambda2 = [&](int foo) {
     96    bool intermediateResult = externalFunction(foo);
     97    return intermediateResult || comparisonVariable < 4;
     98  };
     99 
    100  // Test with an explicit capture
    101  auto lambda3 = [&comparisonVariable](int foo) {
    102    bool intermediateResult = externalFunction(foo);
    103    return intermediateResult || comparisonVariable < 4;
    104  };
    105 
    106  bar = MOZ_VALIDATE_AND_GET(foo, lambda1(foo));
    107  ASSERT_EQ(bar, EXPECTED_INT);
    108 
    109  // Test with a comment
    110  bar = MOZ_VALIDATE_AND_GET(foo, lambda1(foo), "Test comment.");
    111  ASSERT_EQ(bar, EXPECTED_INT);
    112 
    113  // Test with a default capture mode
    114  bar = MOZ_VALIDATE_AND_GET(foo, lambda2(foo), "Test comment.");
    115  ASSERT_EQ(bar, EXPECTED_INT);
    116 
    117  bar = MOZ_VALIDATE_AND_GET(foo, lambda3(foo), "Test comment.");
    118  ASSERT_EQ(bar, EXPECTED_INT);
    119 
    120  // We can't test MOZ_VALIDATE_AND_GET failing, because that triggers
    121  // a release assert.
    122 }
    123 
    124 // ==================================================================
    125 // MOZ_IS_VALID =====================================================
    126 TEST(Tainting, moz_is_valid)
    127 {
    128  int comparisonVariable = 20;
    129  Tainted<int> foo = Tainted<int>(EXPECTED_INT);
    130 
    131  ASSERT_TRUE(MOZ_IS_VALID(foo, foo < 20));
    132 
    133  ASSERT_FALSE(MOZ_IS_VALID(foo, foo > 20));
    134 
    135  ASSERT_TRUE(MOZ_IS_VALID(foo, foo < comparisonVariable));
    136 
    137  ASSERT_TRUE(
    138      MOZ_IS_VALID(foo, ([&foo]() { return externalFunction(foo); }())));
    139 
    140  ASSERT_TRUE(MOZ_IS_VALID(foo, ([&foo, &comparisonVariable]() {
    141                             bool intermediateResult = externalFunction(foo);
    142                             return intermediateResult ||
    143                                    comparisonVariable < 4;
    144                           }())));
    145 
    146  // External lambdas
    147  auto lambda1 = [](int foo) { return externalFunction(foo); };
    148 
    149  auto lambda2 = [&](int foo) {
    150    bool intermediateResult = externalFunction(foo);
    151    return intermediateResult || comparisonVariable < 4;
    152  };
    153 
    154  // Test with an explicit capture
    155  auto lambda3 = [&comparisonVariable](int foo) {
    156    bool intermediateResult = externalFunction(foo);
    157    return intermediateResult || comparisonVariable < 4;
    158  };
    159 
    160  ASSERT_TRUE(MOZ_IS_VALID(foo, lambda1(foo)));
    161 
    162  ASSERT_TRUE(MOZ_IS_VALID(foo, lambda2(foo)));
    163 
    164  ASSERT_TRUE(MOZ_IS_VALID(foo, lambda3(foo)));
    165 }
    166 
    167 // ==================================================================
    168 // MOZ_VALIDATE_OR ==================================================
    169 TEST(Tainting, moz_validate_or)
    170 {
    171  int result;
    172  int comparisonVariable = 20;
    173  Tainted<int> foo = Tainted<int>(EXPECTED_INT);
    174 
    175  result = MOZ_VALIDATE_OR(foo, foo < 20, 100);
    176  ASSERT_EQ(result, EXPECTED_INT);
    177 
    178  result = MOZ_VALIDATE_OR(foo, foo > 20, 100);
    179  ASSERT_EQ(result, 100);
    180 
    181  result = MOZ_VALIDATE_OR(foo, foo < comparisonVariable, 100);
    182  ASSERT_EQ(result, EXPECTED_INT);
    183 
    184  // External lambdas
    185  auto lambda1 = [](int foo) { return externalFunction(foo); };
    186 
    187  auto lambda2 = [&](int foo) {
    188    bool intermediateResult = externalFunction(foo);
    189    return intermediateResult || comparisonVariable < 4;
    190  };
    191 
    192  // Test with an explicit capture
    193  auto lambda3 = [&comparisonVariable](int foo) {
    194    bool intermediateResult = externalFunction(foo);
    195    return intermediateResult || comparisonVariable < 4;
    196  };
    197 
    198  result = MOZ_VALIDATE_OR(foo, lambda1(foo), 100);
    199  ASSERT_EQ(result, EXPECTED_INT);
    200 
    201  result = MOZ_VALIDATE_OR(foo, lambda2(foo), 100);
    202  ASSERT_EQ(result, EXPECTED_INT);
    203 
    204  result = MOZ_VALIDATE_OR(foo, lambda3(foo), 100);
    205  ASSERT_EQ(result, EXPECTED_INT);
    206 
    207  result =
    208      MOZ_VALIDATE_OR(foo, ([&foo]() { return externalFunction(foo); }()), 100);
    209  ASSERT_EQ(result, EXPECTED_INT);
    210 
    211  // This test is for the lambda variant with a supplied assertion
    212  // string.
    213  result =
    214      MOZ_VALIDATE_OR(foo, ([&foo] { return externalFunction(foo); }()), 100);
    215  ASSERT_EQ(result, EXPECTED_INT);
    216 
    217  // This test is for the lambda variant with a captured variable
    218  result =
    219      MOZ_VALIDATE_OR(foo, ([&foo, &comparisonVariable] {
    220                        bool intermediateResult = externalFunction(foo);
    221                        return intermediateResult || comparisonVariable < 4;
    222                      }()),
    223                      100);
    224  ASSERT_EQ(result, EXPECTED_INT);
    225 
    226  // This test is for the lambda variant with full capture mode
    227  result =
    228      MOZ_VALIDATE_OR(foo, ([&] {
    229                        bool intermediateResult = externalFunction(foo);
    230                        return intermediateResult || comparisonVariable < 4;
    231                      }()),
    232                      100);
    233  ASSERT_EQ(result, EXPECTED_INT);
    234 }
    235 
    236 // ==================================================================
    237 // MOZ_FIND_AND_VALIDATE ============================================
    238 TEST(Tainting, moz_find_and_validate)
    239 {
    240  Tainted<int> foo = Tainted<int>(EXPECTED_INT);
    241  Tainted<char> baz = Tainted<char>(EXPECTED_CHAR);
    242 
    243  //-------------------------------
    244  const mozilla::Array<int, 6> mozarrayWithFoo(0, 5, EXPECTED_INT, 15, 20, 25);
    245  const mozilla::Array<int, 5> mozarrayWithoutFoo(0, 5, 15, 20, 25);
    246 
    247  ASSERT_TRUE(*MOZ_FIND_AND_VALIDATE(foo, list_item == foo, mozarrayWithFoo) ==
    248              mozarrayWithFoo[2]);
    249 
    250  ASSERT_TRUE(MOZ_FIND_AND_VALIDATE(foo, list_item == foo,
    251                                    mozarrayWithoutFoo) == nullptr);
    252 
    253  //-------------------------------
    254  class TestClass {
    255   public:
    256    int a;
    257    int b;
    258 
    259    TestClass(int a, int b) {
    260      this->a = a;
    261      this->b = b;
    262    }
    263 
    264    bool operator==(const TestClass& other) const {
    265      return this->a == other.a && this->b == other.b;
    266    }
    267  };
    268 
    269  const mozilla::Array<TestClass, 5> mozarrayOfClassesWithFoo(
    270      TestClass(0, 1), TestClass(2, 3), TestClass(EXPECTED_INT, EXPECTED_INT),
    271      TestClass(4, 5), TestClass(6, 7));
    272 
    273  ASSERT_TRUE(*MOZ_FIND_AND_VALIDATE(
    274                  foo, foo == list_item.a && foo == list_item.b,
    275                  mozarrayOfClassesWithFoo) == mozarrayOfClassesWithFoo[2]);
    276 
    277  ASSERT_TRUE(*MOZ_FIND_AND_VALIDATE(
    278                  foo, (foo == list_item.a && foo == list_item.b),
    279                  mozarrayOfClassesWithFoo) == mozarrayOfClassesWithFoo[2]);
    280 
    281  ASSERT_TRUE(
    282      *MOZ_FIND_AND_VALIDATE(
    283          foo,
    284          (foo == list_item.a && foo == list_item.b && externalFunction(foo)),
    285          mozarrayOfClassesWithFoo) == mozarrayOfClassesWithFoo[2]);
    286 
    287  ASSERT_TRUE(*MOZ_FIND_AND_VALIDATE(
    288                  foo, ([](int tainted_val, TestClass list_item) {
    289                    return tainted_val == list_item.a &&
    290                           tainted_val == list_item.b;
    291                  }(foo, list_item)),
    292                  mozarrayOfClassesWithFoo) == mozarrayOfClassesWithFoo[2]);
    293 
    294  auto lambda4 = [](int tainted_val, TestClass list_item) {
    295    return tainted_val == list_item.a && tainted_val == list_item.b;
    296  };
    297 
    298  ASSERT_TRUE(*MOZ_FIND_AND_VALIDATE(foo, lambda4(foo, list_item),
    299                                     mozarrayOfClassesWithFoo) ==
    300              mozarrayOfClassesWithFoo[2]);
    301 
    302  //-------------------------------
    303  const char m[] = "m";
    304  const char o[] = "o";
    305  const char z[] = {EXPECTED_CHAR, '\0'};
    306  const char l[] = "l";
    307  const char a[] = "a";
    308 
    309  nsTHashtable<nsCharPtrHashKey> hashtableWithBaz;
    310  hashtableWithBaz.PutEntry(m);
    311  hashtableWithBaz.PutEntry(o);
    312  hashtableWithBaz.PutEntry(z);
    313  hashtableWithBaz.PutEntry(l);
    314  hashtableWithBaz.PutEntry(a);
    315  nsTHashtable<nsCharPtrHashKey> hashtableWithoutBaz;
    316  hashtableWithoutBaz.PutEntry(m);
    317  hashtableWithoutBaz.PutEntry(o);
    318  hashtableWithoutBaz.PutEntry(l);
    319  hashtableWithoutBaz.PutEntry(a);
    320 
    321  ASSERT_TRUE(MOZ_FIND_AND_VALIDATE(baz, *list_item.GetKey() == baz,
    322                                    hashtableWithBaz) ==
    323              hashtableWithBaz.GetEntry(z));
    324 
    325  ASSERT_TRUE(MOZ_FIND_AND_VALIDATE(baz, *list_item.GetKey() == baz,
    326                                    hashtableWithoutBaz) == nullptr);
    327 
    328  //-------------------------------
    329  const nsTArray<int> nsTArrayWithFoo = {0, 5, EXPECTED_INT, 15, 20, 25};
    330  const nsTArray<int> nsTArrayWithoutFoo = {0, 5, 15, 20, 25};
    331 
    332  ASSERT_TRUE(*MOZ_FIND_AND_VALIDATE(foo, list_item == foo, nsTArrayWithFoo) ==
    333              nsTArrayWithFoo[2]);
    334 
    335  ASSERT_TRUE(MOZ_FIND_AND_VALIDATE(foo, list_item == foo,
    336                                    nsTArrayWithoutFoo) == nullptr);
    337 
    338  //-------------------------------
    339  const std::array<int, 6> arrayWithFoo{0, 5, EXPECTED_INT, 15, 20, 25};
    340  const std::array<int, 5> arrayWithoutFoo{0, 5, 15, 20, 25};
    341 
    342  ASSERT_TRUE(*MOZ_FIND_AND_VALIDATE(foo, list_item == foo, arrayWithFoo) ==
    343              arrayWithFoo[2]);
    344 
    345  ASSERT_TRUE(MOZ_FIND_AND_VALIDATE(foo, list_item == foo, arrayWithoutFoo) ==
    346              nullptr);
    347 
    348  //-------------------------------
    349  const std::deque<int> dequeWithFoo{0, 5, EXPECTED_INT, 15, 20, 25};
    350  const std::deque<int> dequeWithoutFoo{0, 5, 15, 20, 25};
    351 
    352  ASSERT_TRUE(*MOZ_FIND_AND_VALIDATE(foo, list_item == foo, dequeWithFoo) ==
    353              dequeWithFoo[2]);
    354 
    355  ASSERT_TRUE(MOZ_FIND_AND_VALIDATE(foo, list_item == foo, dequeWithoutFoo) ==
    356              nullptr);
    357 
    358  //-------------------------------
    359  const std::forward_list<int> forwardWithFoo{0, 5, EXPECTED_INT, 15, 20, 25};
    360  const std::forward_list<int> forwardWithoutFoo{0, 5, 15, 20, 25};
    361 
    362  auto forwardListIt = forwardWithFoo.begin();
    363  std::advance(forwardListIt, 2);
    364 
    365  ASSERT_TRUE(*MOZ_FIND_AND_VALIDATE(foo, list_item == foo, forwardWithFoo) ==
    366              *forwardListIt);
    367 
    368  ASSERT_TRUE(MOZ_FIND_AND_VALIDATE(foo, list_item == foo, forwardWithoutFoo) ==
    369              nullptr);
    370 
    371  //-------------------------------
    372  const std::list<int> listWithFoo{0, 5, EXPECTED_INT, 15, 20, 25};
    373  const std::list<int> listWithoutFoo{0, 5, 15, 20, 25};
    374 
    375  auto listIt = listWithFoo.begin();
    376  std::advance(listIt, 2);
    377 
    378  ASSERT_TRUE(*MOZ_FIND_AND_VALIDATE(foo, list_item == foo, listWithFoo) ==
    379              *listIt);
    380 
    381  ASSERT_TRUE(MOZ_FIND_AND_VALIDATE(foo, list_item == foo, listWithoutFoo) ==
    382              nullptr);
    383 
    384  //-------------------------------
    385  const std::map<std::string, int> mapWithFoo{{
    386      {"zero", 0},
    387      {"five", 5},
    388      {"ten", EXPECTED_INT},
    389      {"fifteen", 15},
    390      {"twenty", 20},
    391      {"twenty-five", 25},
    392  }};
    393  const std::map<std::string, int> mapWithoutFoo{{
    394      {"zero", 0},
    395      {"five", 5},
    396      {"fifteen", 15},
    397      {"twenty", 20},
    398      {"twenty-five", 25},
    399  }};
    400 
    401  const auto map_it = mapWithFoo.find("ten");
    402 
    403  ASSERT_TRUE(
    404      MOZ_FIND_AND_VALIDATE(foo, list_item.second == foo, mapWithFoo)->second ==
    405      map_it->second);
    406 
    407  ASSERT_TRUE(MOZ_FIND_AND_VALIDATE(foo, list_item.second == foo,
    408                                    mapWithoutFoo) == nullptr);
    409 
    410  //-------------------------------
    411  const std::set<int> setWithFoo{0, 5, EXPECTED_INT, 15, 20, 25};
    412  const std::set<int> setWithoutFoo{0, 5, 15, 20, 25};
    413 
    414  auto setIt = setWithFoo.find(EXPECTED_INT);
    415 
    416  ASSERT_TRUE(*MOZ_FIND_AND_VALIDATE(foo, list_item == foo, setWithFoo) ==
    417              *setIt);
    418 
    419  ASSERT_TRUE(MOZ_FIND_AND_VALIDATE(foo, list_item == foo, setWithoutFoo) ==
    420              nullptr);
    421 
    422  //-------------------------------
    423  const std::unordered_map<std::string, int> unordermapWithFoo = {
    424      {"zero", 0},     {"five", 5},    {"ten", EXPECTED_INT},
    425      {"fifteen", 15}, {"twenty", 20}, {"twenty-five", 25},
    426  };
    427  const std::unordered_map<std::string, int> unordermapWithoutFoo{{
    428      {"zero", 0},
    429      {"five", 5},
    430      {"fifteen", 15},
    431      {"twenty", 20},
    432      {"twenty-five", 25},
    433  }};
    434 
    435  auto unorderedMapIt = unordermapWithFoo.find("ten");
    436 
    437  ASSERT_TRUE(
    438      MOZ_FIND_AND_VALIDATE(foo, list_item.second == foo, unordermapWithFoo)
    439          ->second == unorderedMapIt->second);
    440 
    441  ASSERT_TRUE(MOZ_FIND_AND_VALIDATE(foo, list_item.second == foo,
    442                                    unordermapWithoutFoo) == nullptr);
    443 
    444  //-------------------------------
    445  const std::unordered_set<int> unorderedsetWithFoo{0,  5,  EXPECTED_INT,
    446                                                    15, 20, 25};
    447  const std::unordered_set<int> unorderedsetWithoutFoo{0, 5, 15, 20, 25};
    448 
    449  auto unorderedSetIt = unorderedsetWithFoo.find(EXPECTED_INT);
    450 
    451  ASSERT_TRUE(*MOZ_FIND_AND_VALIDATE(foo, list_item == foo,
    452                                     unorderedsetWithFoo) == *unorderedSetIt);
    453 
    454  ASSERT_TRUE(MOZ_FIND_AND_VALIDATE(foo, list_item == foo,
    455                                    unorderedsetWithoutFoo) == nullptr);
    456 
    457  //-------------------------------
    458  const std::vector<int> vectorWithFoo{0, 5, EXPECTED_INT, 15, 20, 25};
    459  const std::vector<int> vectorWithoutFoo{0, 5, 15, 20, 25};
    460 
    461  ASSERT_TRUE(*MOZ_FIND_AND_VALIDATE(foo, list_item == foo, vectorWithFoo) ==
    462              vectorWithFoo[2]);
    463 
    464  ASSERT_TRUE(MOZ_FIND_AND_VALIDATE(foo, list_item == foo, vectorWithoutFoo) ==
    465              nullptr);
    466 }
    467 
    468 // ==================================================================
    469 // MOZ_NO_VALIDATE ==================================================
    470 TEST(Tainting, moz_no_validate)
    471 {
    472  int result;
    473  Tainted<int> foo = Tainted<int>(EXPECTED_INT);
    474 
    475  result = MOZ_NO_VALIDATE(
    476      foo,
    477      "Value is used to match against a dictionary key in the parent."
    478      "If there's no key present, there won't be a match."
    479      "There is no risk of grabbing a cross-origin value from the dictionary,"
    480      "because the IPC actor is instatiated per-content-process and the "
    481      "dictionary is not shared between actors.");
    482  ASSERT_TRUE(result == EXPECTED_INT);
    483 }