tor-browser

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

TestCSPParser.cpp (46539B)


      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
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include <stdlib.h>
      8 #include <string.h>
      9 
     10 #include "gtest/gtest.h"
     11 #include "mozilla/BasePrincipal.h"
     12 #include "mozilla/dom/nsCSPContext.h"
     13 #include "mozilla/gtest/MozAssertions.h"
     14 #include "nsComponentManagerUtils.h"
     15 #include "nsIContentSecurityPolicy.h"
     16 #include "nsIPrefBranch.h"
     17 #include "nsIPrefService.h"
     18 #include "nsNetUtil.h"
     19 #include "nsStringFwd.h"
     20 
     21 /*
     22 * Testing the parser is non trivial, especially since we can not call
     23 * parser functionality directly in compiled code tests.
     24 * All the tests (except the fuzzy tests at the end) follow the same schemata:
     25 *   a) create an nsIContentSecurityPolicy object
     26 *   b) set the selfURI in SetRequestContextWithPrincipal
     27 *   c) append one or more policies by calling AppendPolicy
     28 *   d) check if the policy count is correct by calling GetPolicyCount
     29 *   e) compare the result of the policy with the expected output
     30 *      using the struct PolicyTest;
     31 *
     32 * In general we test:
     33 * a) policies that the parser should accept
     34 * b) policies that the parser should reject
     35 * c) policies that are randomly generated (fuzzy tests)
     36 *
     37 * Please note that fuzzy tests are *DISABLED* by default and shold only
     38 * be run *OFFLINE* whenever code in nsCSPParser changes.
     39 * To run fuzzy tests, flip RUN_OFFLINE_TESTS to 1.
     40 *
     41 */
     42 
     43 #define RUN_OFFLINE_TESTS 0
     44 
     45 /*
     46 * Offline tests are separated in three different groups:
     47 *  * TestFuzzyPolicies - complete random ASCII input
     48 *  * TestFuzzyPoliciesIncDir - a directory name followed by random ASCII
     49 *  * TestFuzzyPoliciesIncDirLimASCII - a directory name followed by limited
     50 * ASCII which represents more likely user input.
     51 *
     52 *  We run each of this categories |kFuzzyRuns| times.
     53 */
     54 
     55 #if RUN_OFFLINE_TESTS
     56 static const uint32_t kFuzzyRuns = 10000;
     57 #endif
     58 
     59 // For fuzzy testing we actually do not care about the output,
     60 // we just want to make sure that the parser can handle random
     61 // input, therefore we use kFuzzyExpectedPolicyCount to return early.
     62 static const uint32_t kFuzzyExpectedPolicyCount = 111;
     63 
     64 static const uint32_t kMaxPolicyLength = 96;
     65 
     66 struct PolicyTest {
     67  char policy[kMaxPolicyLength];
     68  char expectedResult[kMaxPolicyLength];
     69 };
     70 
     71 nsresult runTest(
     72    uint32_t aExpectedPolicyCount,  // this should be 0 for policies which
     73                                    // should fail to parse
     74    const char* aPolicy, const char* aExpectedResult) {
     75  nsresult rv;
     76 
     77  // we init the csp with http://www.selfuri.com
     78  nsCOMPtr<nsIURI> selfURI;
     79  rv = NS_NewURI(getter_AddRefs(selfURI), "http://www.selfuri.com");
     80  NS_ENSURE_SUCCESS(rv, rv);
     81 
     82  nsCOMPtr<nsIPrincipal> selfURIPrincipal;
     83  mozilla::OriginAttributes attrs;
     84  selfURIPrincipal =
     85      mozilla::BasePrincipal::CreateContentPrincipal(selfURI, attrs);
     86  NS_ENSURE_TRUE(selfURIPrincipal, NS_ERROR_FAILURE);
     87 
     88  // create a CSP object
     89  nsCOMPtr<nsIContentSecurityPolicy> csp =
     90      do_CreateInstance(NS_CSPCONTEXT_CONTRACTID, &rv);
     91  NS_ENSURE_SUCCESS(rv, rv);
     92 
     93  // for testing the parser we only need to set a principal which is needed
     94  // to translate the keyword 'self' into an actual URI.
     95  rv = csp->SetRequestContextWithPrincipal(selfURIPrincipal, selfURI, ""_ns, 0);
     96  NS_ENSURE_SUCCESS(rv, rv);
     97 
     98  // append a policy
     99  nsString policyStr;
    100  policyStr.AssignASCII(aPolicy);
    101  rv = csp->AppendPolicy(policyStr, false, false);
    102  NS_ENSURE_SUCCESS(rv, rv);
    103 
    104  // when executing fuzzy tests we do not care about the actual output
    105  // of the parser, we just want to make sure that the parser is not crashing.
    106  if (aExpectedPolicyCount == kFuzzyExpectedPolicyCount) {
    107    return NS_OK;
    108  }
    109 
    110  // verify that the expected number of policies exists
    111  uint32_t actualPolicyCount;
    112  rv = csp->GetPolicyCount(&actualPolicyCount);
    113  NS_ENSURE_SUCCESS(rv, rv);
    114  if (actualPolicyCount != aExpectedPolicyCount) {
    115    EXPECT_TRUE(false)
    116        << "Actual policy count not equal to expected policy count ("
    117        << actualPolicyCount << " != " << aExpectedPolicyCount
    118        << ") for policy: " << aPolicy;
    119    return NS_ERROR_UNEXPECTED;
    120  }
    121 
    122  // if the expected policy count is 0, we can return, because
    123  // we can not compare any output anyway. Used when parsing
    124  // errornous policies.
    125  if (aExpectedPolicyCount == 0) {
    126    return NS_OK;
    127  }
    128 
    129  // compare the parsed policy against the expected result
    130  nsString parsedPolicyStr;
    131  // checking policy at index 0, which is the one what we appended.
    132  rv = csp->GetPolicyString(0, parsedPolicyStr);
    133  NS_ENSURE_SUCCESS(rv, rv);
    134 
    135  if (!NS_ConvertUTF16toUTF8(parsedPolicyStr).EqualsASCII(aExpectedResult)) {
    136    EXPECT_TRUE(false) << "Actual policy does not match expected policy ("
    137                       << NS_ConvertUTF16toUTF8(parsedPolicyStr).get()
    138                       << " != " << aExpectedResult << ")";
    139    return NS_ERROR_UNEXPECTED;
    140  }
    141 
    142  return NS_OK;
    143 }
    144 
    145 // ============================= run Tests ========================
    146 
    147 nsresult runTestSuite(const PolicyTest* aPolicies, uint32_t aPolicyCount,
    148                      uint32_t aExpectedPolicyCount) {
    149  nsresult rv;
    150  nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
    151 
    152  // Add prefs you need to set to parse CSP here, see comments for example
    153  // bool examplePref = false;
    154  bool trustedTypesEnabled = false;
    155  constexpr auto kTrustedTypesEnabledPrefName =
    156      "dom.security.trusted_types.enabled";
    157  if (prefs) {
    158    // prefs->GetBoolPref("security.csp.examplePref", &examplePref);
    159    // prefs->SetBoolPref("security.csp.examplePref", true);
    160    prefs->GetBoolPref(kTrustedTypesEnabledPrefName, &trustedTypesEnabled);
    161    prefs->SetBoolPref(kTrustedTypesEnabledPrefName, true);
    162  }
    163 
    164  for (uint32_t i = 0; i < aPolicyCount; i++) {
    165    rv = runTest(aExpectedPolicyCount, aPolicies[i].policy,
    166                 aPolicies[i].expectedResult);
    167    NS_ENSURE_SUCCESS(rv, rv);
    168  }
    169 
    170  if (prefs) {
    171    // prefs->SetBoolPref("security.csp.examplePref", examplePref);
    172    prefs->SetBoolPref(kTrustedTypesEnabledPrefName, trustedTypesEnabled);
    173  }
    174 
    175  return NS_OK;
    176 }
    177 
    178 // ============================= TestDirectives ========================
    179 
    180 TEST(CSPParser, Directives)
    181 {
    182  static const PolicyTest policies[] = {
    183      // clang-format off
    184    { "connect-src xn--mnchen-3ya.de",
    185      "connect-src http://xn--mnchen-3ya.de"},
    186    { "default-src http://www.example.com",
    187      "default-src http://www.example.com" },
    188    { "script-src http://www.example.com",
    189      "script-src http://www.example.com" },
    190    { "object-src http://www.example.com",
    191      "object-src http://www.example.com" },
    192    { "style-src http://www.example.com",
    193      "style-src http://www.example.com" },
    194    { "img-src http://www.example.com",
    195      "img-src http://www.example.com" },
    196    { "media-src http://www.example.com",
    197      "media-src http://www.example.com" },
    198    { "frame-src http://www.example.com",
    199      "frame-src http://www.example.com" },
    200    { "font-src http://www.example.com",
    201      "font-src http://www.example.com" },
    202    { "connect-src http://www.example.com",
    203      "connect-src http://www.example.com" },
    204    { "report-uri http://www.example.com",
    205      "report-uri http://www.example.com/" },
    206    { "script-src 'nonce-correctscriptnonce'",
    207      "script-src 'nonce-correctscriptnonce'" },
    208    { "script-src 'nonce-a'",
    209      "script-src 'nonce-a'" },
    210    { "script-src 'sha256-a'",
    211      "script-src 'sha256-a'" },
    212    { "script-src 'sha256-siVR8vAcqP06h2ppeNwqgjr0yZ6yned4X2VF84j4GmI='",
    213      "script-src 'sha256-siVR8vAcqP06h2ppeNwqgjr0yZ6yned4X2VF84j4GmI='" },
    214    { "script-src 'nonce-foo' 'unsafe-inline' ",
    215      "script-src 'nonce-foo' 'unsafe-inline'" },
    216    { "script-src 'nonce-foo' 'strict-dynamic' 'unsafe-inline' https:  ",
    217      "script-src 'nonce-foo' 'strict-dynamic' 'unsafe-inline' https:" },
    218    { "script-src 'nonce-foo' 'strict-dynamic' 'unsafe-inline' 'report-sample' https:  ",
    219      "script-src 'nonce-foo' 'strict-dynamic' 'unsafe-inline' 'report-sample' https:" },
    220    { "default-src 'sha256-siVR8' 'strict-dynamic' 'unsafe-inline' https:  ",
    221      "default-src 'sha256-siVR8' 'strict-dynamic' 'unsafe-inline' https:" },
    222    { "worker-src https://example.com",
    223      "worker-src https://example.com" },
    224    { "worker-src http://worker.com; frame-src http://frame.com; child-src http://child.com",
    225      "worker-src http://worker.com; frame-src http://frame.com; child-src http://child.com" },
    226    { "script-src 'unsafe-allow-redirects' http://example.com",
    227      "script-src http://example.com"},
    228    { "require-trusted-types-for 'script'",
    229      "require-trusted-types-for 'script'" },
    230    { "require-trusted-types-for 'script' invalid",
    231      "require-trusted-types-for 'script' invalid" }, // bug 1956731
    232    { "require-trusted-types-for 'script' 'invalid'",
    233      "require-trusted-types-for 'script' 'invalid'" }, // bug 1956731
    234    { "trusted-types somePolicyName", "trusted-types somePolicyName" },
    235    { "trusted-types somePolicyName anotherPolicyName 1 - # = _ / @ . % *",
    236      "trusted-types somePolicyName anotherPolicyName 1 - # = _ / @ . % *" },
    237    { "trusted-types $", "trusted-types $" }, // bug 1935434
    238    { "trusted-types 'invalid'", "trusted-types 'invalid'" }, // bug 1935434
    239      // clang-format on
    240  };
    241 
    242  uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);
    243  ASSERT_NS_SUCCEEDED(runTestSuite(policies, policyCount, 1));
    244 }
    245 
    246 // ============================= TestKeywords ========================
    247 
    248 TEST(CSPParser, Keywords)
    249 {
    250  static const PolicyTest policies[] = {
    251      // clang-format off
    252    { "script-src 'self'",
    253      "script-src 'self'" },
    254    { "script-src 'unsafe-inline'",
    255      "script-src 'unsafe-inline'" },
    256    { "script-src 'unsafe-eval'",
    257      "script-src 'unsafe-eval'" },
    258    { "script-src 'unsafe-inline' 'unsafe-eval'",
    259      "script-src 'unsafe-inline' 'unsafe-eval'" },
    260    { "script-src 'none'",
    261      "script-src 'none'" },
    262    { "script-src 'wasm-unsafe-eval'",
    263      "script-src 'wasm-unsafe-eval'" },
    264    { "img-src 'none'; script-src 'unsafe-eval' 'unsafe-inline'; default-src 'self'",
    265      "img-src 'none'; script-src 'unsafe-eval' 'unsafe-inline'; default-src 'self'" },
    266    { "trusted-types somePolicyName 'allow-duplicates'",
    267      "trusted-types somePolicyName 'allow-duplicates'" },
    268    { "trusted-types 'none'", "trusted-types 'none'" },
    269    { "trusted-types", "trusted-types 'none'" },
    270    { "trusted-types 'none' somePolicyName", "trusted-types somePolicyName" },
    271    { "trusted-types 'none' 'none'", "trusted-types 'none'" },
    272    { "trusted-types 'none' 'allow-duplicates'", "trusted-types 'allow-duplicates'" },
    273    { "trusted-types 'none' *", "trusted-types *" },
    274    { "trusted-types *", "trusted-types *" },
    275      // clang-format on
    276  };
    277 
    278  uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);
    279  ASSERT_NS_SUCCEEDED(runTestSuite(policies, policyCount, 1));
    280 }
    281 
    282 // =================== TestIgnoreUpperLowerCasePolicies ==============
    283 
    284 TEST(CSPParser, IgnoreUpperLowerCasePolicies)
    285 {
    286  static const PolicyTest policies[] = {
    287      // clang-format off
    288    { "script-src 'SELF'",
    289      "script-src 'self'" },
    290    { "sCriPt-src 'Unsafe-Inline'",
    291      "script-src 'unsafe-inline'" },
    292    { "SCRIPT-src 'unsafe-eval'",
    293      "script-src 'unsafe-eval'" },
    294    { "default-SRC 'unsafe-inline' 'unsafe-eval'",
    295      "default-src 'unsafe-inline' 'unsafe-eval'" },
    296    { "script-src 'NoNe'",
    297      "script-src 'none'" },
    298    { "img-sRc 'noNe'; scrIpt-src 'unsafe-EVAL' 'UNSAFE-inline'; deFAULT-src 'Self'",
    299      "img-src 'none'; script-src 'unsafe-eval' 'unsafe-inline'; default-src 'self'" },
    300    { "default-src HTTP://www.example.com",
    301      "default-src http://www.example.com" },
    302    { "default-src HTTP://WWW.EXAMPLE.COM",
    303      "default-src http://www.example.com" },
    304    { "default-src HTTPS://*.example.COM",
    305      "default-src https://*.example.com" },
    306    { "script-src 'none' test.com;",
    307      "script-src http://test.com" },
    308    { "script-src 'NoNCE-correctscriptnonce'",
    309      "script-src 'nonce-correctscriptnonce'" },
    310    { "script-src 'NoncE-NONCENEEDSTOBEUPPERCASE'",
    311      "script-src 'nonce-NONCENEEDSTOBEUPPERCASE'" },
    312    { "script-src 'SHA256-siVR8vAcqP06h2ppeNwqgjr0yZ6yned4X2VF84j4GmI='",
    313      "script-src 'sha256-siVR8vAcqP06h2ppeNwqgjr0yZ6yned4X2VF84j4GmI='" },
    314    { "upgrade-INSECURE-requests",
    315      "upgrade-insecure-requests" },
    316    { "sanDBox alloW-foRMs",
    317      "sandbox allow-forms"},
    318      // clang-format on
    319  };
    320 
    321  uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);
    322  ASSERT_NS_SUCCEEDED(runTestSuite(policies, policyCount, 1));
    323 }
    324 
    325 // ========================= TestPaths ===============================
    326 
    327 TEST(CSPParser, Paths)
    328 {
    329  static const PolicyTest policies[] = {
    330      // clang-format off
    331    { "script-src http://www.example.com",
    332      "script-src http://www.example.com" },
    333    { "script-src http://www.example.com/",
    334      "script-src http://www.example.com/" },
    335    { "script-src http://www.example.com/path-1",
    336      "script-src http://www.example.com/path-1" },
    337    { "script-src http://www.example.com/path-1/",
    338      "script-src http://www.example.com/path-1/" },
    339    { "script-src http://www.example.com/path-1/path_2",
    340      "script-src http://www.example.com/path-1/path_2" },
    341    { "script-src http://www.example.com/path-1/path_2/",
    342      "script-src http://www.example.com/path-1/path_2/" },
    343    { "script-src http://www.example.com/path-1/path_2/file.js",
    344      "script-src http://www.example.com/path-1/path_2/file.js" },
    345    { "script-src http://www.example.com/path-1/path_2/file_1.js",
    346      "script-src http://www.example.com/path-1/path_2/file_1.js" },
    347    { "script-src http://www.example.com/path-1/path_2/file-2.js",
    348      "script-src http://www.example.com/path-1/path_2/file-2.js" },
    349    { "script-src http://www.example.com/path-1/path_2/f.js",
    350      "script-src http://www.example.com/path-1/path_2/f.js" },
    351    { "script-src http://www.example.com:88",
    352      "script-src http://www.example.com:88" },
    353    { "script-src http://www.example.com:88/",
    354      "script-src http://www.example.com:88/" },
    355    { "script-src http://www.example.com:88/path-1",
    356      "script-src http://www.example.com:88/path-1" },
    357    { "script-src http://www.example.com:88/path-1/",
    358      "script-src http://www.example.com:88/path-1/" },
    359    { "script-src http://www.example.com:88/path-1/path_2",
    360      "script-src http://www.example.com:88/path-1/path_2" },
    361    { "script-src http://www.example.com:88/path-1/path_2/",
    362      "script-src http://www.example.com:88/path-1/path_2/" },
    363    { "script-src http://www.example.com:88/path-1/path_2/file.js",
    364      "script-src http://www.example.com:88/path-1/path_2/file.js" },
    365    { "script-src http://www.example.com:*",
    366      "script-src http://www.example.com:*" },
    367    { "script-src http://www.example.com:*/",
    368      "script-src http://www.example.com:*/" },
    369    { "script-src http://www.example.com:*/path-1",
    370      "script-src http://www.example.com:*/path-1" },
    371    { "script-src http://www.example.com:*/path-1/",
    372      "script-src http://www.example.com:*/path-1/" },
    373    { "script-src http://www.example.com:*/path-1/path_2",
    374      "script-src http://www.example.com:*/path-1/path_2" },
    375    { "script-src http://www.example.com:*/path-1/path_2/",
    376      "script-src http://www.example.com:*/path-1/path_2/" },
    377    { "script-src http://www.example.com:*/path-1/path_2/file.js",
    378      "script-src http://www.example.com:*/path-1/path_2/file.js" },
    379    { "script-src http://www.example.com#foo",
    380      "script-src http://www.example.com" },
    381    { "script-src http://www.example.com?foo=bar",
    382      "script-src http://www.example.com" },
    383    { "script-src http://www.example.com:8888#foo",
    384      "script-src http://www.example.com:8888" },
    385    { "script-src http://www.example.com:8888?foo",
    386      "script-src http://www.example.com:8888" },
    387    { "script-src http://www.example.com/#foo",
    388      "script-src http://www.example.com/" },
    389    { "script-src http://www.example.com/?foo",
    390      "script-src http://www.example.com/" },
    391    { "script-src http://www.example.com/path-1/file.js#foo",
    392      "script-src http://www.example.com/path-1/file.js" },
    393    { "script-src http://www.example.com/path-1/file.js?foo",
    394      "script-src http://www.example.com/path-1/file.js" },
    395    { "script-src http://www.example.com/path-1/file.js?foo#bar",
    396      "script-src http://www.example.com/path-1/file.js" },
    397    { "report-uri http://www.example.com/",
    398      "report-uri http://www.example.com/" },
    399    { "report-uri http://www.example.com:8888/asdf",
    400      "report-uri http://www.example.com:8888/asdf" },
    401    { "report-uri http://www.example.com:8888/path_1/path_2",
    402      "report-uri http://www.example.com:8888/path_1/path_2" },
    403    { "report-uri http://www.example.com:8888/path_1/path_2/report.sjs&301",
    404      "report-uri http://www.example.com:8888/path_1/path_2/report.sjs&301" },
    405    { "report-uri /examplepath",
    406      "report-uri http://www.selfuri.com/examplepath" },
    407    { "connect-src http://www.example.com/foo%3Bsessionid=12%2C34",
    408      "connect-src http://www.example.com/foo;sessionid=12,34" },
    409    { "connect-src http://www.example.com/foo%3bsessionid=12%2c34",
    410      "connect-src http://www.example.com/foo;sessionid=12,34" },
    411    { "connect-src http://test.com/pathIncludingAz19-._~!$&'()*+=:@",
    412      "connect-src http://test.com/pathIncludingAz19-._~!$&'()*+=:@" },
    413    { "script-src http://www.example.com:88/.js",
    414      "script-src http://www.example.com:88/.js" },
    415    { "script-src https://foo.com/_abc/abc_/_/_a_b_c_",
    416      "script-src https://foo.com/_abc/abc_/_/_a_b_c_" }  // clang-format on
    417  };
    418 
    419  uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);
    420  ASSERT_NS_SUCCEEDED(runTestSuite(policies, policyCount, 1));
    421 }
    422 
    423 // ======================== TestSimplePolicies =======================
    424 
    425 TEST(CSPParser, SimplePolicies)
    426 {
    427  static const PolicyTest policies[] = {
    428      // clang-format off
    429    { "frame-src intent:",
    430      "frame-src intent:" },
    431    { "frame-src intent://host.name",
    432      "frame-src intent://host.name" },
    433    { "frame-src intent://my.host.link/",
    434      "frame-src intent://my.host.link/" },
    435    { "default-src *",
    436      "default-src *" },
    437    { "default-src https:",
    438      "default-src https:" },
    439    { "default-src https://*",
    440      "default-src https://*" },
    441    { "default-src *:*",
    442      "default-src http://*:*" },
    443    { "default-src *:80",
    444      "default-src http://*:80" },
    445    { "default-src http://*:80",
    446      "default-src http://*:80" },
    447    { "default-src javascript:",
    448      "default-src javascript:" },
    449    { "default-src data:",
    450      "default-src data:" },
    451    { "script-src 'unsafe-eval' 'unsafe-inline' http://www.example.com",
    452      "script-src 'unsafe-eval' 'unsafe-inline' http://www.example.com" },
    453    { "object-src 'self'",
    454      "object-src 'self'" },
    455    { "style-src http://www.example.com 'self'",
    456      "style-src http://www.example.com 'self'" },
    457    { "media-src http://www.example.com http://www.test.com",
    458      "media-src http://www.example.com http://www.test.com" },
    459    { "connect-src http://www.test.com example.com *.other.com;",
    460      "connect-src http://www.test.com http://example.com http://*.other.com"},
    461    { "connect-src example.com *.other.com",
    462      "connect-src http://example.com http://*.other.com"},
    463    { "style-src *.other.com example.com",
    464      "style-src http://*.other.com http://example.com"},
    465    { "default-src 'self'; img-src *;",
    466      "default-src 'self'; img-src *" },
    467    { "object-src media1.example.com media2.example.com *.cdn.example.com;",
    468      "object-src http://media1.example.com http://media2.example.com http://*.cdn.example.com" },
    469    { "script-src trustedscripts.example.com",
    470      "script-src http://trustedscripts.example.com" },
    471    { "script-src 'self' ; default-src trustedscripts.example.com",
    472      "script-src 'self'; default-src http://trustedscripts.example.com" },
    473    { "default-src 'none'; report-uri http://localhost:49938/test",
    474      "default-src 'none'; report-uri http://localhost:49938/test" },
    475    { "   ;   default-src abc",
    476      "default-src http://abc" },
    477    { " ; ; ; ;     default-src            abc    ; ; ; ;",
    478      "default-src http://abc" },
    479    { "script-src 'none' 'none' 'none';",
    480      "script-src 'none'" },
    481    { "script-src http://www.example.com/path-1//",
    482      "script-src http://www.example.com/path-1//" },
    483    { "script-src http://www.example.com/path-1//path_2",
    484      "script-src http://www.example.com/path-1//path_2" },
    485    { "default-src 127.0.0.1",
    486      "default-src http://127.0.0.1" },
    487    { "default-src 127.0.0.1:*",
    488      "default-src http://127.0.0.1:*" },
    489    { "default-src -; ",
    490      "default-src http://-" },
    491    { "script-src 1",
    492      "script-src http://1" },
    493    { "upgrade-insecure-requests",
    494      "upgrade-insecure-requests" },
    495    { "upgrade-insecure-requests https:",
    496      "upgrade-insecure-requests" },
    497    { "sandbox allow-scripts allow-forms  ",
    498      "sandbox allow-scripts allow-forms" },
    499      // clang-format on
    500  };
    501 
    502  uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);
    503  ASSERT_NS_SUCCEEDED(runTestSuite(policies, policyCount, 1));
    504 }
    505 
    506 // =================== TestPoliciesWithInvalidSrc ====================
    507 
    508 TEST(CSPParser, PoliciesWithInvalidSrc)
    509 {
    510  static const PolicyTest policies[] = {
    511      // clang-format off
    512    { "script-src 'self'; SCRIPT-SRC http://www.example.com",
    513      "script-src 'self'" },
    514    { "script-src 'none' test.com; script-src example.com",
    515      "script-src http://test.com" },
    516    { "default-src **",
    517      "default-src 'none'" },
    518    { "default-src 'self",
    519      "default-src 'none'" },
    520    { "default-src 'unsafe-inlin' ",
    521      "default-src 'none'" },
    522    { "default-src */",
    523      "default-src 'none'" },
    524    { "default-src",
    525      "default-src 'none'" },
    526    { "default-src 'unsafe-inlin' ",
    527      "default-src 'none'" },
    528    { "default-src :88",
    529      "default-src 'none'" },
    530    { "script-src abc::::::88",
    531      "script-src 'none'" },
    532    { "script-src *.*:*",
    533      "script-src 'none'" },
    534    { "img-src *::88",
    535      "img-src 'none'" },
    536    { "object-src http://localhost:",
    537      "object-src 'none'" },
    538    { "script-src test..com",
    539      "script-src 'none'" },
    540    { "script-src sub1.sub2.example+",
    541      "script-src 'none'" },
    542    { "script-src http://www.example.com//",
    543      "script-src 'none'" },
    544    { "script-src http://www.example.com:88path-1/",
    545      "script-src 'none'" },
    546    { "script-src http://www.example.com:88//",
    547      "script-src 'none'" },
    548    { "script-src http://www.example.com:88//path-1",
    549      "script-src 'none'" },
    550    { "script-src http://www.example.com:88//path-1",
    551      "script-src 'none'" },
    552    { "script-src http://www.example.com:88.js",
    553      "script-src 'none'" },
    554    { "script-src http://www.example.com:*.js",
    555      "script-src 'none'" },
    556    { "script-src http://www.example.com:*.",
    557      "script-src 'none'" },
    558    { "script-src 'nonce-{invalid}'",
    559      "script-src 'none'" },
    560    { "script-src 'sha256-{invalid}'",
    561      "script-src 'none'" },
    562    { "script-src 'nonce-in$valid'",
    563      "script-src 'none'" },
    564    { "script-src 'sha256-in$valid'",
    565      "script-src 'none'" },
    566    { "script-src 'nonce-invalid==='",
    567      "script-src 'none'" },
    568    { "script-src 'sha256-invalid==='",
    569      "script-src 'none'" },
    570    { "script-src 'nonce-==='",
    571      "script-src 'none'" },
    572    { "script-src 'sha256-==='",
    573      "script-src 'none'" },
    574    { "script-src 'nonce-=='",
    575      "script-src 'none'" },
    576    { "script-src 'sha256-=='",
    577      "script-src 'none'" },
    578    { "script-src 'nonce-='",
    579      "script-src 'none'" },
    580    { "script-src 'sha256-='",
    581      "script-src 'none'" },
    582    { "script-src 'nonce-'",
    583      "script-src 'none'" },
    584    { "script-src 'sha256-'",
    585      "script-src 'none'" },
    586    { "connect-src http://www.example.com/foo%zz;",
    587      "connect-src 'none'" },
    588    { "script-src https://foo.com/%$",
    589      "script-src 'none'" },
    590    { "sandbox    foo",
    591      "sandbox"},
    592      // clang-format on
    593  };
    594 
    595  // amount of tests - 1, because the latest should be ignored.
    596  uint32_t policyCount = (sizeof(policies) / sizeof(PolicyTest)) - 1;
    597  ASSERT_NS_SUCCEEDED(runTestSuite(policies, policyCount, 1));
    598 }
    599 
    600 // ============================= TestBadPolicies =======================
    601 
    602 TEST(CSPParser, BadPolicies)
    603 {
    604  static const PolicyTest policies[] = {
    605      // clang-format off
    606    { "script-sr 'self", "" },
    607    { "", "" },
    608    { "; ; ; ; ; ; ;", "" },
    609    { "defaut-src asdf", "" },
    610    { "default-src: aaa", "" },
    611    { "asdf http://test.com", ""},
    612    { "report-uri", ""},
    613    { "report-uri http://:foo", ""},
    614    { "require-sri-for", ""},
    615    { "require-sri-for style", ""},
    616    { "require-trusted-types-for invalid" },
    617    { "require-trusted-types-for 'invalid'" },
    618 
    619      // clang-format on
    620  };
    621 
    622  uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);
    623  ASSERT_NS_SUCCEEDED(runTestSuite(policies, policyCount, 0));
    624 }
    625 
    626 // ======================= TestGoodGeneratedPolicies =================
    627 
    628 TEST(CSPParser, GoodGeneratedPolicies)
    629 {
    630  static const PolicyTest policies[] = {
    631      // clang-format off
    632    { "default-src 'self'; img-src *",
    633      "default-src 'self'; img-src *" },
    634    { "report-uri /policy",
    635      "report-uri http://www.selfuri.com/policy"},
    636    { "img-src *",
    637      "img-src *" },
    638    { "media-src foo.bar",
    639      "media-src http://foo.bar" },
    640    { "frame-src *.bar",
    641      "frame-src http://*.bar" },
    642    { "font-src com",
    643      "font-src http://com" },
    644    { "connect-src f00b4r.com",
    645      "connect-src http://f00b4r.com" },
    646    { "script-src *.a.b.c",
    647      "script-src http://*.a.b.c" },
    648    { "object-src *.b.c",
    649      "object-src http://*.b.c" },
    650    { "style-src a.b.c",
    651      "style-src http://a.b.c" },
    652    { "img-src a.com",
    653      "img-src http://a.com" },
    654    { "media-src http://abc.com",
    655      "media-src http://abc.com" },
    656    { "frame-src a2-c.com",
    657      "frame-src http://a2-c.com" },
    658    { "font-src https://a.com",
    659      "font-src https://a.com" },
    660    { "connect-src *.a.com",
    661      "connect-src http://*.a.com" },
    662    { "default-src a.com:23",
    663      "default-src http://a.com:23" },
    664    { "script-src https://a.com:200",
    665      "script-src https://a.com:200" },
    666    { "object-src data:",
    667      "object-src data:" },
    668    { "style-src javascript:",
    669      "style-src javascript:" },
    670    { "frame-src https://foobar.com:443",
    671      "frame-src https://foobar.com:443" },
    672    { "font-src https://a.com:443",
    673      "font-src https://a.com:443" },
    674    { "connect-src http://a.com:80",
    675      "connect-src http://a.com:80" },
    676    { "default-src http://foobar.com",
    677      "default-src http://foobar.com" },
    678    { "script-src https://foobar.com",
    679      "script-src https://foobar.com" },
    680    { "style-src 'none'",
    681      "style-src 'none'" },
    682    { "img-src foo.bar:21 https://ras.bar",
    683      "img-src http://foo.bar:21 https://ras.bar" },
    684    { "media-src http://foo.bar:21 https://ras.bar:443",
    685      "media-src http://foo.bar:21 https://ras.bar:443" },
    686    { "frame-src http://self.com:80",
    687      "frame-src http://self.com:80" },
    688    { "font-src http://self.com",
    689      "font-src http://self.com" },
    690    { "connect-src https://foo.com http://bar.com:88",
    691      "connect-src https://foo.com http://bar.com:88" },
    692    { "default-src * https://bar.com 'none'",
    693      "default-src * https://bar.com" },
    694    { "script-src *.foo.com",
    695      "script-src http://*.foo.com" },
    696    { "object-src http://b.com",
    697      "object-src http://b.com" },
    698    { "style-src http://bar.com:88",
    699      "style-src http://bar.com:88" },
    700    { "img-src https://bar.com:88",
    701      "img-src https://bar.com:88" },
    702    { "media-src http://bar.com:443",
    703      "media-src http://bar.com:443" },
    704    { "frame-src https://foo.com:88",
    705      "frame-src https://foo.com:88" },
    706    { "font-src http://foo.com",
    707      "font-src http://foo.com" },
    708    { "connect-src http://x.com:23",
    709      "connect-src http://x.com:23" },
    710    { "default-src http://barbaz.com",
    711      "default-src http://barbaz.com" },
    712    { "script-src http://somerandom.foo.com",
    713      "script-src http://somerandom.foo.com" },
    714    { "default-src *",
    715      "default-src *" },
    716    { "style-src http://bar.com:22",
    717      "style-src http://bar.com:22" },
    718    { "img-src https://foo.com:443",
    719      "img-src https://foo.com:443" },
    720    { "script-src https://foo.com; ",
    721      "script-src https://foo.com" },
    722    { "img-src bar.com:*",
    723      "img-src http://bar.com:*" },
    724    { "font-src https://foo.com:400",
    725      "font-src https://foo.com:400" },
    726    { "connect-src http://bar.com:400",
    727      "connect-src http://bar.com:400" },
    728    { "default-src http://evil.com",
    729      "default-src http://evil.com" },
    730    { "script-src https://evil.com:100",
    731      "script-src https://evil.com:100" },
    732    { "default-src bar.com; script-src https://foo.com",
    733      "default-src http://bar.com; script-src https://foo.com" },
    734    { "default-src 'self'; script-src 'self' https://*:*",
    735      "default-src 'self'; script-src 'self' https://*:*" },
    736    { "img-src http://self.com:34",
    737      "img-src http://self.com:34" },
    738    { "media-src http://subd.self.com:34",
    739      "media-src http://subd.self.com:34" },
    740    { "default-src 'none'",
    741      "default-src 'none'" },
    742    { "connect-src http://self",
    743      "connect-src http://self" },
    744    { "default-src http://foo",
    745      "default-src http://foo" },
    746    { "script-src http://foo:80",
    747      "script-src http://foo:80" },
    748    { "object-src http://bar",
    749      "object-src http://bar" },
    750    { "style-src http://three:80",
    751      "style-src http://three:80" },
    752    { "img-src https://foo:400",
    753      "img-src https://foo:400" },
    754    { "media-src https://self:34",
    755      "media-src https://self:34" },
    756    { "frame-src https://bar",
    757      "frame-src https://bar" },
    758    { "font-src http://three:81",
    759      "font-src http://three:81" },
    760    { "connect-src https://three:81",
    761      "connect-src https://three:81" },
    762    { "script-src http://self.com:80/foo",
    763      "script-src http://self.com:80/foo" },
    764    { "object-src http://self.com/foo",
    765      "object-src http://self.com/foo" },
    766    { "report-uri /report.py",
    767      "report-uri http://www.selfuri.com/report.py"},
    768    { "img-src http://foo.org:34/report.py",
    769      "img-src http://foo.org:34/report.py" },
    770    { "media-src foo/bar/report.py",
    771      "media-src http://foo/bar/report.py" },
    772    { "report-uri /",
    773      "report-uri http://www.selfuri.com/"},
    774    { "font-src https://self.com/report.py",
    775      "font-src https://self.com/report.py" },
    776    { "connect-src https://foo.com/report.py",
    777      "connect-src https://foo.com/report.py" },
    778    { "default-src *; report-uri  http://www.reporturi.com/",
    779      "default-src *; report-uri http://www.reporturi.com/" },
    780    { "default-src http://first.com",
    781      "default-src http://first.com" },
    782    { "script-src http://second.com",
    783      "script-src http://second.com" },
    784    { "object-src http://third.com",
    785      "object-src http://third.com" },
    786    { "style-src https://foobar.com:4443",
    787      "style-src https://foobar.com:4443" },
    788    { "img-src http://foobar.com:4443",
    789      "img-src http://foobar.com:4443" },
    790    { "media-src bar.com",
    791      "media-src http://bar.com" },
    792    { "frame-src http://bar.com",
    793      "frame-src http://bar.com" },
    794    { "font-src http://self.com/",
    795      "font-src http://self.com/" },
    796    { "script-src 'self'",
    797      "script-src 'self'" },
    798    { "default-src http://self.com/foo.png",
    799      "default-src http://self.com/foo.png" },
    800    { "script-src http://self.com/foo.js",
    801      "script-src http://self.com/foo.js" },
    802    { "object-src http://bar.com/foo.js",
    803      "object-src http://bar.com/foo.js" },
    804    { "style-src http://FOO.COM",
    805      "style-src http://foo.com" },
    806    { "img-src HTTP",
    807      "img-src http://http" },
    808    { "media-src http",
    809      "media-src http://http" },
    810    { "frame-src 'SELF'",
    811      "frame-src 'self'" },
    812    { "DEFAULT-src 'self';",
    813      "default-src 'self'" },
    814    { "default-src 'self' http://FOO.COM",
    815      "default-src 'self' http://foo.com" },
    816    { "default-src 'self' HTTP://foo.com",
    817      "default-src 'self' http://foo.com" },
    818    { "default-src 'NONE'",
    819      "default-src 'none'" },
    820    { "script-src policy-uri ",
    821      "script-src http://policy-uri" },
    822    { "img-src 'self'; ",
    823      "img-src 'self'" },
    824    { "frame-ancestors foo-bar.com",
    825      "frame-ancestors http://foo-bar.com" },
    826    { "frame-ancestors http://a.com",
    827      "frame-ancestors http://a.com" },
    828    { "frame-ancestors 'self'",
    829      "frame-ancestors 'self'" },
    830    { "frame-ancestors http://self.com:88",
    831      "frame-ancestors http://self.com:88" },
    832    { "frame-ancestors http://a.b.c.d.e.f.g.h.i.j.k.l.x.com",
    833      "frame-ancestors http://a.b.c.d.e.f.g.h.i.j.k.l.x.com" },
    834    { "frame-ancestors https://self.com:34",
    835      "frame-ancestors https://self.com:34" },
    836    { "frame-ancestors http://sampleuser:samplepass@example.com",
    837      "frame-ancestors 'none'" },
    838    { "default-src 'none'; frame-ancestors 'self'",
    839      "default-src 'none'; frame-ancestors 'self'" },
    840    { "frame-ancestors http://self:80",
    841      "frame-ancestors http://self:80" },
    842    { "frame-ancestors http://self.com/bar",
    843      "frame-ancestors http://self.com/bar" },
    844    { "default-src 'self'; frame-ancestors 'self'",
    845      "default-src 'self'; frame-ancestors 'self'" },
    846    { "frame-ancestors http://bar.com/foo.png",
    847      "frame-ancestors http://bar.com/foo.png" },
    848      // clang-format on
    849  };
    850 
    851  uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);
    852  ASSERT_NS_SUCCEEDED(runTestSuite(policies, policyCount, 1));
    853 }
    854 
    855 // ==================== TestBadGeneratedPolicies ====================
    856 
    857 TEST(CSPParser, BadGeneratedPolicies)
    858 {
    859  static const PolicyTest policies[] = {
    860      // clang-format off
    861    { "foo.*.bar", ""},
    862    { "foo!bar.com", ""},
    863    { "x.*.a.com", ""},
    864    { "a#2-c.com", ""},
    865    { "http://foo.com:bar.com:23", ""},
    866    { "f!oo.bar", ""},
    867    { "ht!ps://f-oo.bar", ""},
    868    { "https://f-oo.bar:3f", ""},
    869    { "**", ""},
    870    { "*a", ""},
    871    { "http://username:password@self.com/foo", ""},
    872    { "http://other:pass1@self.com/foo", ""},
    873    { "http://user1:pass1@self.com/foo", ""},
    874    { "http://username:password@self.com/bar", ""},
    875      // clang-format on
    876  };
    877 
    878  uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);
    879  ASSERT_NS_SUCCEEDED(runTestSuite(policies, policyCount, 0));
    880 }
    881 
    882 // ============ TestGoodGeneratedPoliciesForPathHandling =============
    883 
    884 TEST(CSPParser, GoodGeneratedPoliciesForPathHandling)
    885 {
    886  // Once bug 808292 (Implement path-level host-source matching to CSP)
    887  // lands we have to update the expected output to include the parsed path
    888 
    889  static const PolicyTest policies[] = {
    890      // clang-format off
    891    { "img-src http://test1.example.com",
    892      "img-src http://test1.example.com" },
    893    { "img-src http://test1.example.com/",
    894      "img-src http://test1.example.com/" },
    895    { "img-src http://test1.example.com/path-1",
    896      "img-src http://test1.example.com/path-1" },
    897    { "img-src http://test1.example.com/path-1/",
    898      "img-src http://test1.example.com/path-1/" },
    899    { "img-src http://test1.example.com/path-1/path_2/",
    900      "img-src http://test1.example.com/path-1/path_2/" },
    901    { "img-src http://test1.example.com/path-1/path_2/file.js",
    902      "img-src http://test1.example.com/path-1/path_2/file.js" },
    903    { "img-src http://test1.example.com/path-1/path_2/file_1.js",
    904      "img-src http://test1.example.com/path-1/path_2/file_1.js" },
    905    { "img-src http://test1.example.com/path-1/path_2/file-2.js",
    906      "img-src http://test1.example.com/path-1/path_2/file-2.js" },
    907    { "img-src http://test1.example.com/path-1/path_2/f.js",
    908      "img-src http://test1.example.com/path-1/path_2/f.js" },
    909    { "img-src http://test1.example.com/path-1/path_2/f.oo.js",
    910      "img-src http://test1.example.com/path-1/path_2/f.oo.js" },
    911    { "img-src test1.example.com",
    912      "img-src http://test1.example.com" },
    913    { "img-src test1.example.com/",
    914      "img-src http://test1.example.com/" },
    915    { "img-src test1.example.com/path-1",
    916      "img-src http://test1.example.com/path-1" },
    917    { "img-src test1.example.com/path-1/",
    918      "img-src http://test1.example.com/path-1/" },
    919    { "img-src test1.example.com/path-1/path_2/",
    920      "img-src http://test1.example.com/path-1/path_2/" },
    921    { "img-src test1.example.com/path-1/path_2/file.js",
    922      "img-src http://test1.example.com/path-1/path_2/file.js" },
    923    { "img-src test1.example.com/path-1/path_2/file_1.js",
    924      "img-src http://test1.example.com/path-1/path_2/file_1.js" },
    925    { "img-src test1.example.com/path-1/path_2/file-2.js",
    926      "img-src http://test1.example.com/path-1/path_2/file-2.js" },
    927    { "img-src test1.example.com/path-1/path_2/f.js",
    928      "img-src http://test1.example.com/path-1/path_2/f.js" },
    929    { "img-src test1.example.com/path-1/path_2/f.oo.js",
    930      "img-src http://test1.example.com/path-1/path_2/f.oo.js" },
    931    { "img-src *.example.com",
    932      "img-src http://*.example.com" },
    933    { "img-src *.example.com/",
    934      "img-src http://*.example.com/" },
    935    { "img-src *.example.com/path-1",
    936      "img-src http://*.example.com/path-1" },
    937    { "img-src *.example.com/path-1/",
    938      "img-src http://*.example.com/path-1/" },
    939    { "img-src *.example.com/path-1/path_2/",
    940      "img-src http://*.example.com/path-1/path_2/" },
    941    { "img-src *.example.com/path-1/path_2/file.js",
    942      "img-src http://*.example.com/path-1/path_2/file.js" },
    943    { "img-src *.example.com/path-1/path_2/file_1.js",
    944      "img-src http://*.example.com/path-1/path_2/file_1.js" },
    945    { "img-src *.example.com/path-1/path_2/file-2.js",
    946      "img-src http://*.example.com/path-1/path_2/file-2.js" },
    947    { "img-src *.example.com/path-1/path_2/f.js",
    948      "img-src http://*.example.com/path-1/path_2/f.js" },
    949    { "img-src *.example.com/path-1/path_2/f.oo.js",
    950      "img-src http://*.example.com/path-1/path_2/f.oo.js" },
    951    { "img-src test1.example.com:80",
    952      "img-src http://test1.example.com:80" },
    953    { "img-src test1.example.com:80/",
    954      "img-src http://test1.example.com:80/" },
    955    { "img-src test1.example.com:80/path-1",
    956      "img-src http://test1.example.com:80/path-1" },
    957    { "img-src test1.example.com:80/path-1/",
    958      "img-src http://test1.example.com:80/path-1/" },
    959    { "img-src test1.example.com:80/path-1/path_2",
    960      "img-src http://test1.example.com:80/path-1/path_2" },
    961    { "img-src test1.example.com:80/path-1/path_2/",
    962      "img-src http://test1.example.com:80/path-1/path_2/" },
    963    { "img-src test1.example.com:80/path-1/path_2/file.js",
    964      "img-src http://test1.example.com:80/path-1/path_2/file.js" },
    965    { "img-src test1.example.com:80/path-1/path_2/f.ile.js",
    966      "img-src http://test1.example.com:80/path-1/path_2/f.ile.js" },
    967    { "img-src test1.example.com:*",
    968      "img-src http://test1.example.com:*" },
    969    { "img-src test1.example.com:*/",
    970      "img-src http://test1.example.com:*/" },
    971    { "img-src test1.example.com:*/path-1",
    972      "img-src http://test1.example.com:*/path-1" },
    973    { "img-src test1.example.com:*/path-1/",
    974      "img-src http://test1.example.com:*/path-1/" },
    975    { "img-src test1.example.com:*/path-1/path_2",
    976      "img-src http://test1.example.com:*/path-1/path_2" },
    977    { "img-src test1.example.com:*/path-1/path_2/",
    978      "img-src http://test1.example.com:*/path-1/path_2/" },
    979    { "img-src test1.example.com:*/path-1/path_2/file.js",
    980      "img-src http://test1.example.com:*/path-1/path_2/file.js" },
    981    { "img-src test1.example.com:*/path-1/path_2/f.ile.js",
    982      "img-src http://test1.example.com:*/path-1/path_2/f.ile.js" },
    983    { "img-src http://test1.example.com/abc//",
    984      "img-src http://test1.example.com/abc//" },
    985    { "img-src https://test1.example.com/abc/def//",
    986      "img-src https://test1.example.com/abc/def//" },
    987    { "img-src https://test1.example.com/abc/def/ghi//",
    988      "img-src https://test1.example.com/abc/def/ghi//" },
    989    { "img-src http://test1.example.com:80/abc//",
    990      "img-src http://test1.example.com:80/abc//" },
    991    { "img-src https://test1.example.com:80/abc/def//",
    992      "img-src https://test1.example.com:80/abc/def//" },
    993    { "img-src https://test1.example.com:80/abc/def/ghi//",
    994      "img-src https://test1.example.com:80/abc/def/ghi//" },
    995    { "img-src https://test1.example.com/abc////////////def/",
    996      "img-src https://test1.example.com/abc////////////def/" },
    997    { "img-src https://test1.example.com/abc////////////",
    998      "img-src https://test1.example.com/abc////////////" },
    999      // clang-format on
   1000  };
   1001 
   1002  uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);
   1003  ASSERT_NS_SUCCEEDED(runTestSuite(policies, policyCount, 1));
   1004 }
   1005 
   1006 // ============== TestBadGeneratedPoliciesForPathHandling ============
   1007 
   1008 TEST(CSPParser, BadGeneratedPoliciesForPathHandling)
   1009 {
   1010  static const PolicyTest policies[] = {
   1011      // clang-format off
   1012    { "img-src test1.example.com:88path-1/",
   1013      "img-src 'none'" },
   1014    { "img-src test1.example.com:80.js",
   1015      "img-src 'none'" },
   1016    { "img-src test1.example.com:*.js",
   1017      "img-src 'none'" },
   1018    { "img-src test1.example.com:*.",
   1019      "img-src 'none'" },
   1020    { "img-src http://test1.example.com//",
   1021      "img-src 'none'" },
   1022    { "img-src http://test1.example.com:80//",
   1023      "img-src 'none'" },
   1024    { "img-src http://test1.example.com:80abc",
   1025      "img-src 'none'" },
   1026      // clang-format on
   1027  };
   1028 
   1029  uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);
   1030  ASSERT_NS_SUCCEEDED(runTestSuite(policies, policyCount, 1));
   1031 }
   1032 
   1033 // ======================== TestFuzzyPolicies ========================
   1034 
   1035 // Use a policy, eliminate one character at a time,
   1036 // and feed it as input to the parser.
   1037 
   1038 TEST(CSPParser, ShorteningPolicies)
   1039 {
   1040  char pol[] =
   1041      "default-src http://www.sub1.sub2.example.com:88/path1/path2/ "
   1042      "'unsafe-inline' 'none'";
   1043  uint32_t len = static_cast<uint32_t>(sizeof(pol));
   1044 
   1045  PolicyTest testPol[1];
   1046  memset(&testPol[0].policy, '\0', kMaxPolicyLength * sizeof(char));
   1047 
   1048  while (--len) {
   1049    memset(&testPol[0].policy, '\0', kMaxPolicyLength * sizeof(char));
   1050    memcpy(&testPol[0].policy, &pol, len * sizeof(char));
   1051    ASSERT_TRUE(
   1052        NS_SUCCEEDED(runTestSuite(testPol, 1, kFuzzyExpectedPolicyCount)));
   1053  }
   1054 }
   1055 
   1056 // ============================= TestFuzzyPolicies ===================
   1057 
   1058 // We generate kFuzzyRuns inputs by (pseudo) randomly picking from the 128
   1059 // ASCII characters; feed them to the parser and verfy that the parser
   1060 // handles the input gracefully.
   1061 //
   1062 // Please note, that by using srand(0) we get deterministic results!
   1063 
   1064 #if RUN_OFFLINE_TESTS
   1065 
   1066 TEST(CSPParser, FuzzyPolicies)
   1067 {
   1068  // init srand with 0 so we get same results
   1069  srand(0);
   1070 
   1071  PolicyTest testPol[1];
   1072  memset(&testPol[0].policy, '\0', kMaxPolicyLength);
   1073 
   1074  for (uint32_t index = 0; index < kFuzzyRuns; index++) {
   1075    // randomly select the length of the next policy
   1076    uint32_t polLength = rand() % kMaxPolicyLength;
   1077    // reset memory of the policy string
   1078    memset(&testPol[0].policy, '\0', kMaxPolicyLength * sizeof(char));
   1079 
   1080    for (uint32_t i = 0; i < polLength; i++) {
   1081      // fill the policy array with random ASCII chars
   1082      testPol[0].policy[i] = static_cast<char>(rand() % 128);
   1083    }
   1084    ASSERT_TRUE(
   1085        NS_SUCCEEDED(runTestSuite(testPol, 1, kFuzzyExpectedPolicyCount)));
   1086  }
   1087 }
   1088 
   1089 #endif
   1090 
   1091 // ======================= TestFuzzyPoliciesIncDir ===================
   1092 
   1093 // In a similar fashion as in TestFuzzyPolicies, we again (pseudo) randomly
   1094 // generate input for the parser, but this time also include a valid directive
   1095 // followed by the random input.
   1096 
   1097 #if RUN_OFFLINE_TESTS
   1098 
   1099 TEST(CSPParser, FuzzyPoliciesIncDir)
   1100 {
   1101  // init srand with 0 so we get same results
   1102  srand(0);
   1103 
   1104  PolicyTest testPol[1];
   1105  memset(&testPol[0].policy, '\0', kMaxPolicyLength);
   1106 
   1107  char defaultSrc[] = "default-src ";
   1108  int defaultSrcLen = sizeof(defaultSrc) - 1;
   1109  // copy default-src into the policy array
   1110  memcpy(&testPol[0].policy, &defaultSrc, (defaultSrcLen * sizeof(char)));
   1111 
   1112  for (uint32_t index = 0; index < kFuzzyRuns; index++) {
   1113    // randomly select the length of the next policy
   1114    uint32_t polLength = rand() % (kMaxPolicyLength - defaultSrcLen);
   1115    // reset memory of the policy string, but leave default-src.
   1116    memset((&(testPol[0].policy) + (defaultSrcLen * sizeof(char))), '\0',
   1117           (kMaxPolicyLength - defaultSrcLen) * sizeof(char));
   1118 
   1119    // do not start at index 0 so we do not overwrite 'default-src'
   1120    for (uint32_t i = defaultSrcLen; i < polLength; i++) {
   1121      // fill the policy array with random ASCII chars
   1122      testPol[0].policy[i] = static_cast<char>(rand() % 128);
   1123    }
   1124    ASSERT_TRUE(
   1125        NS_SUCCEEDED(runTestSuite(testPol, 1, kFuzzyExpectedPolicyCount)));
   1126  }
   1127 }
   1128 
   1129 #endif
   1130 
   1131 // ====================== TestFuzzyPoliciesIncDirLimASCII ============
   1132 
   1133 // Same as TestFuzzyPoliciesIncDir() but using limited ASCII,
   1134 // which represents more likely input.
   1135 
   1136 #if RUN_OFFLINE_TESTS
   1137 
   1138 TEST(CSPParser, FuzzyPoliciesIncDirLimASCII)
   1139 {
   1140  char input[] =
   1141      "1234567890"
   1142      "abcdefghijklmnopqrstuvwxyz"
   1143      "ABCDEFGHIJKLMNOPQRSTUVWZYZ"
   1144      "!@#^&*()-+_=";
   1145 
   1146  // init srand with 0 so we get same results
   1147  srand(0);
   1148 
   1149  PolicyTest testPol[1];
   1150  memset(&testPol[0].policy, '\0', kMaxPolicyLength);
   1151 
   1152  char defaultSrc[] = "default-src ";
   1153  int defaultSrcLen = sizeof(defaultSrc) - 1;
   1154  // copy default-src into the policy array
   1155  memcpy(&testPol[0].policy, &defaultSrc, (defaultSrcLen * sizeof(char)));
   1156 
   1157  for (uint32_t index = 0; index < kFuzzyRuns; index++) {
   1158    // randomly select the length of the next policy
   1159    uint32_t polLength = rand() % (kMaxPolicyLength - defaultSrcLen);
   1160    // reset memory of the policy string, but leave default-src.
   1161    memset((&(testPol[0].policy) + (defaultSrcLen * sizeof(char))), '\0',
   1162           (kMaxPolicyLength - defaultSrcLen) * sizeof(char));
   1163 
   1164    // do not start at index 0 so we do not overwrite 'default-src'
   1165    for (uint32_t i = defaultSrcLen; i < polLength; i++) {
   1166      // fill the policy array with chars from the pre-defined input
   1167      uint32_t inputIndex = rand() % sizeof(input);
   1168      testPol[0].policy[i] = input[inputIndex];
   1169    }
   1170    ASSERT_TRUE(
   1171        NS_SUCCEEDED(runTestSuite(testPol, 1, kFuzzyExpectedPolicyCount)));
   1172  }
   1173 }
   1174 #endif