tor-browser

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

Parser.cpp (15780B)


      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 "gtest/gtest.h"
      8 #include "Preferences.h"
      9 
     10 using namespace mozilla;
     11 
     12 // Keep this in sync with the declaration in Preferences.cpp.
     13 //
     14 // It's declared here to avoid polluting Preferences.h with test-only stuff.
     15 void TestParseError(PrefValueKind aKind, const char* aText,
     16                    nsCString& aErrorMsg);
     17 
     18 TEST(PrefsParser, Errors)
     19 {
     20  nsAutoCStringN<128> actualErrorMsg;
     21 
     22 // Use a macro rather than a function so that the line number reported by
     23 // gtest on failure is useful.
     24 #define P(kind_, text_, expectedErrorMsg_)                 \
     25  do {                                                     \
     26    TestParseError(kind_, text_, actualErrorMsg);          \
     27    ASSERT_STREQ(expectedErrorMsg_, actualErrorMsg.get()); \
     28  } while (0)
     29 
     30 #define DEFAULT(text_, expectedErrorMsg_) \
     31  P(PrefValueKind::Default, text_, expectedErrorMsg_)
     32 
     33 #define USER(text_, expectedErrorMsg_) \
     34  P(PrefValueKind::User, text_, expectedErrorMsg_)
     35 
     36  // clang-format off
     37 
     38  //-------------------------------------------------------------------------
     39  // Valid syntax. (Other testing of more typical valid syntax and semantics is
     40  // done in modules/libpref/test/unit/test_parser.js.)
     41  //-------------------------------------------------------------------------
     42 
     43  // Normal prefs.
     44  DEFAULT(R"(
     45 pref("bool", true);
     46 sticky_pref("int", 123);
     47 user_pref("string", "value");
     48    )",
     49    ""
     50  );
     51 
     52  // Totally empty input.
     53  DEFAULT("", "");
     54 
     55  // Whitespace-only input.
     56  DEFAULT(R"(
     57 
     58    )" "\v \t \v \f",
     59    ""
     60  );
     61 
     62  // Comment-only inputs.
     63  DEFAULT(R"(// blah)", "");
     64  DEFAULT(R"(# blah)", "");
     65  DEFAULT(R"(/* blah */)", "");
     66 
     67  //-------------------------------------------------------------------------
     68  // All the lexing errors. (To be pedantic, some of the integer literal
     69  // overflows are triggered in the parser, but put them all here so they're all
     70  // in the one spot.)
     71  //-------------------------------------------------------------------------
     72 
     73  // Integer overflow errors.
     74  DEFAULT(R"(
     75 pref("int.ok", 2147483647);
     76 pref("int.overflow", 2147483648);
     77 pref("int.ok", +2147483647);
     78 pref("int.overflow", +2147483648);
     79 pref("int.ok", -2147483648);
     80 pref("int.overflow", -2147483649);
     81 pref("int.overflow", 4294967296);
     82 pref("int.overflow", +4294967296);
     83 pref("int.overflow", -4294967296);
     84 pref("int.overflow", 4294967297);
     85 pref("int.overflow", 1234567890987654321);
     86    )",
     87    "test:3: prefs parse error: integer literal overflowed\n"
     88    "test:5: prefs parse error: integer literal overflowed\n"
     89    "test:7: prefs parse error: integer literal overflowed\n"
     90    "test:8: prefs parse error: integer literal overflowed\n"
     91    "test:9: prefs parse error: integer literal overflowed\n"
     92    "test:10: prefs parse error: integer literal overflowed\n"
     93    "test:11: prefs parse error: integer literal overflowed\n"
     94    "test:12: prefs parse error: integer literal overflowed\n"
     95  );
     96 
     97  // Other integer errors.
     98  DEFAULT(R"(
     99 pref("int.unexpected", 100foo);
    100 pref("int.ok", 0);
    101    )",
    102    "test:2: prefs parse error: unexpected character in integer literal\n"
    103  );
    104 
    105  // \x00 is not allowed.
    106  DEFAULT(R"(
    107 pref("string.bad-x-escape", "foo\x00bar");
    108 pref("int.ok", 0);
    109    )",
    110    "test:2: prefs parse error: \\x00 is not allowed\n"
    111  );
    112 
    113  // Various bad things after \x: end of string, punctuation, space, newline,
    114  // EOF.
    115  DEFAULT(R"(
    116 pref("string.bad-x-escape", "foo\x");
    117 pref("string.bad-x-escape", "foo\x,bar");
    118 pref("string.bad-x-escape", "foo\x 12");
    119 pref("string.bad-x-escape", "foo\x
    120 12");
    121 pref("string.bad-x-escape", "foo\x)",
    122    "test:2: prefs parse error: malformed \\x escape sequence\n"
    123    "test:3: prefs parse error: malformed \\x escape sequence\n"
    124    "test:4: prefs parse error: malformed \\x escape sequence\n"
    125    "test:5: prefs parse error: malformed \\x escape sequence\n"
    126    "test:7: prefs parse error: malformed \\x escape sequence\n"
    127  );
    128 
    129  // Not enough hex digits.
    130  DEFAULT(R"(
    131 pref("string.bad-x-escape", "foo\x1");
    132 pref("int.ok", 0);
    133    )",
    134    "test:2: prefs parse error: malformed \\x escape sequence\n"
    135  );
    136 
    137  // Invalid hex digit.
    138  DEFAULT(R"(
    139 pref("string.bad-x-escape", "foo\x1G");
    140 pref("int.ok", 0);
    141    )",
    142    "test:2: prefs parse error: malformed \\x escape sequence\n"
    143  );
    144 
    145  // \u0000 is not allowed.
    146  // (The string literal is broken in two so that MSVC doesn't complain about
    147  // an invalid universal-character-name.)
    148  DEFAULT(R"(
    149 pref("string.bad-u-escape", "foo\)" R"(u0000 bar");
    150 pref("int.ok", 0);
    151    )",
    152    "test:2: prefs parse error: \\u0000 is not allowed\n"
    153  );
    154 
    155  // Various bad things after \u: end of string, punctuation, space, newline,
    156  // EOF.
    157  DEFAULT(R"(
    158 pref("string.bad-u-escape", "foo\u");
    159 pref("string.bad-u-escape", "foo\u,bar");
    160 pref("string.bad-u-escape", "foo\u 1234");
    161 pref("string.bad-u-escape", "foo\u
    162 1234");
    163 pref("string.bad-u-escape", "foo\u)",
    164    "test:2: prefs parse error: malformed \\u escape sequence\n"
    165    "test:3: prefs parse error: malformed \\u escape sequence\n"
    166    "test:4: prefs parse error: malformed \\u escape sequence\n"
    167    "test:5: prefs parse error: malformed \\u escape sequence\n"
    168    "test:7: prefs parse error: malformed \\u escape sequence\n"
    169  );
    170 
    171  // Not enough hex digits.
    172  DEFAULT(R"(
    173 pref("string.bad-u-escape", "foo\u1");
    174 pref("string.bad-u-escape", "foo\u12");
    175 pref("string.bad-u-escape", "foo\u123");
    176 pref("int.ok", 0);
    177    )",
    178    "test:2: prefs parse error: malformed \\u escape sequence\n"
    179    "test:3: prefs parse error: malformed \\u escape sequence\n"
    180    "test:4: prefs parse error: malformed \\u escape sequence\n"
    181  );
    182 
    183  // Invalid hex digit.
    184  DEFAULT(R"(
    185 pref("string.bad-u-escape", "foo\u1G34");
    186 pref("int.ok", 0);
    187    )",
    188    "test:2: prefs parse error: malformed \\u escape sequence\n"
    189  );
    190 
    191  // High surrogate not followed by low surrogate.
    192  // (The string literal is broken in two so that MSVC doesn't complain about
    193  // an invalid universal-character-name.)
    194  DEFAULT(R"(
    195 pref("string.bad-u-surrogate", "foo\)" R"(ud83c,blah");
    196 pref("int.ok", 0);
    197    )",
    198    "test:2: prefs parse error: expected low surrogate after high surrogate\n"
    199  );
    200 
    201  // High surrogate followed by invalid low surrogate.
    202  // (The string literal is broken in two so that MSVC doesn't complain about
    203  // an invalid universal-character-name.)
    204  DEFAULT(R"(
    205 pref("string.bad-u-surrogate", "foo\)" R"(ud83c\u1234");
    206 pref("int.ok", 0);
    207    )",
    208    "test:2: prefs parse error: invalid low surrogate after high surrogate\n"
    209  );
    210 
    211  // Low surrogate not preceded by high surrogate.
    212  // (The string literal is broken in two so that MSVC doesn't complain about
    213  // an invalid universal-character-name.)
    214  DEFAULT(R"(
    215 pref("string.bad-u-surrogate", "foo\)" R"(udc00");
    216 pref("int.ok", 0);
    217    )",
    218    "test:2: prefs parse error: expected high surrogate before low surrogate\n"
    219  );
    220 
    221  // Unlike in JavaScript, \b, \f, \t, \v aren't allowed.
    222  DEFAULT(R"(
    223 pref("string.bad-escape", "foo\b");
    224 pref("string.bad-escape", "foo\f");
    225 pref("string.bad-escape", "foo\t");
    226 pref("string.bad-escape", "foo\v");
    227 pref("int.ok", 0);
    228    )",
    229    "test:2: prefs parse error: unexpected escape sequence character after '\\'\n"
    230    "test:3: prefs parse error: unexpected escape sequence character after '\\'\n"
    231    "test:4: prefs parse error: unexpected escape sequence character after '\\'\n"
    232    "test:5: prefs parse error: unexpected escape sequence character after '\\'\n"
    233  );
    234 
    235  // Various bad things after \: non-special letter, number, punctuation,
    236  // space, newline, EOF.
    237  DEFAULT(R"(
    238 pref("string.bad-escape", "foo\Q");
    239 pref("string.bad-escape", "foo\1");
    240 pref("string.bad-escape", "foo\,");
    241 pref("string.bad-escape", "foo\ n");
    242 pref("string.bad-escape", "foo\
    243 n");
    244 pref("string.bad-escape", "foo\)",
    245    "test:2: prefs parse error: unexpected escape sequence character after '\\'\n"
    246    "test:3: prefs parse error: unexpected escape sequence character after '\\'\n"
    247    "test:4: prefs parse error: unexpected escape sequence character after '\\'\n"
    248    "test:5: prefs parse error: unexpected escape sequence character after '\\'\n"
    249    "test:6: prefs parse error: unexpected escape sequence character after '\\'\n"
    250    "test:8: prefs parse error: unexpected escape sequence character after '\\'\n"
    251  );
    252 
    253  // Unterminated string literals.
    254 
    255  // Simple case.
    256  DEFAULT(R"(
    257 pref("string.unterminated-string", "foo
    258    )",
    259    "test:3: prefs parse error: unterminated string literal\n"
    260  );
    261 
    262  // Alternative case; `int` comes after the string and is seen as a keyword.
    263  // The parser then skips to the ';', so no error about the unterminated
    264  // string is issued.
    265  DEFAULT(R"(
    266 pref("string.unterminated-string", "foo);
    267 pref("int.ok", 0);
    268    )",
    269    "test:3: prefs parse error: unknown keyword\n"
    270  );
    271 
    272  // Mismatched quotes (1).
    273  DEFAULT(R"(
    274 pref("string.unterminated-string", "foo');
    275    )",
    276    "test:3: prefs parse error: unterminated string literal\n"
    277  );
    278 
    279  // Mismatched quotes (2).
    280  DEFAULT(R"(
    281 pref("string.unterminated-string", 'foo");
    282    )",
    283    "test:3: prefs parse error: unterminated string literal\n"
    284  );
    285 
    286  // Unknown keywords.
    287  DEFAULT(R"(
    288 foo;
    289 preff("string.bad-keyword", true);
    290 ticky_pref("string.bad-keyword", true);
    291 User_pref("string.bad-keyword", true);
    292 pref("string.bad-keyword", TRUE);
    293    )",
    294    "test:2: prefs parse error: unknown keyword\n"
    295    "test:3: prefs parse error: unknown keyword\n"
    296    "test:4: prefs parse error: unknown keyword\n"
    297    "test:5: prefs parse error: unknown keyword\n"
    298    "test:6: prefs parse error: unknown keyword\n"
    299  );
    300 
    301  // Unterminated C-style comment.
    302  DEFAULT(R"(
    303 /* comment
    304    )",
    305    "test:3: prefs parse error: unterminated /* comment\n"
    306  );
    307 
    308  // Malformed comments (single slashes), followed by whitespace, newline, EOF.
    309  DEFAULT(R"(
    310 / comment;
    311 /
    312 ; /)",
    313    "test:2: prefs parse error: expected '/' or '*' after '/'\n"
    314    "test:3: prefs parse error: expected '/' or '*' after '/'\n"
    315    "test:4: prefs parse error: expected '/' or '*' after '/'\n"
    316  );
    317 
    318  // C++-style comment ending in EOF (1).
    319  DEFAULT(R"(
    320 // comment)",
    321    ""
    322  );
    323 
    324  // C++-style comment ending in EOF (2).
    325  DEFAULT(R"(
    326 //)",
    327    ""
    328  );
    329 
    330  // Various unexpected characters.
    331  DEFAULT(R"(
    332 pref("unexpected.chars", &true);
    333 pref("unexpected.chars" : true);
    334 @pref("unexpected.chars", true);
    335 pref["unexpected.chars": true];
    336    )",
    337    "test:2: prefs parse error: unexpected character\n"
    338    "test:3: prefs parse error: unexpected character\n"
    339    "test:4: prefs parse error: unexpected character\n"
    340    "test:5: prefs parse error: unexpected character\n"
    341  );
    342 
    343  //-------------------------------------------------------------------------
    344  // All the parsing errors.
    345  //-------------------------------------------------------------------------
    346 
    347  DEFAULT(R"(
    348 "pref"("parse.error": true);
    349 pref1("parse.error": true);
    350 pref(123: true);
    351 pref("parse.error" true);
    352 pref("parse.error", pref);
    353 pref("parse.error", -true);
    354 pref("parse.error", +"value");
    355 pref("parse.error", true,);
    356 pref("parse.error", true;
    357 pref("parse.error", true, sticky, locked;
    358 pref("parse.error", true)
    359 pref("int.ok", 1);
    360 pref("parse.error", true))",
    361    "test:2: prefs parse error: expected pref specifier at start of pref definition\n"
    362    "test:3: prefs parse error: expected '(' after pref specifier\n"
    363    "test:4: prefs parse error: expected pref name after '('\n"
    364    "test:5: prefs parse error: expected ',' after pref name\n"
    365    "test:6: prefs parse error: expected pref value after ','\n"
    366    "test:7: prefs parse error: expected integer literal after '-'\n"
    367    "test:8: prefs parse error: expected integer literal after '+'\n"
    368    "test:9: prefs parse error: expected pref attribute after ','\n"
    369    "test:10: prefs parse error: expected ',' or ')' after pref value\n"
    370    "test:11: prefs parse error: expected ',' or ')' after pref attribute\n"
    371    "test:13: prefs parse error: expected ';' after ')'\n"
    372    "test:14: prefs parse error: expected ';' after ')'\n"
    373  );
    374 
    375  USER(R"(
    376 pref("parse.error", true);
    377 sticky_pref("parse.error", true);
    378 user_pref("int.ok", 1);
    379    )",
    380    "test:2: prefs parse error: expected 'user_pref' at start of pref definition\n"
    381    "test:3: prefs parse error: expected 'user_pref' at start of pref definition\n"
    382  );
    383 
    384  USER(R"(
    385 user_pref("parse.error", true;
    386 user_pref("int.ok", 1);
    387    )",
    388    "test:2: prefs parse error: expected ')' after pref value\n"
    389  );
    390 
    391  // Parse errors involving unexpected EOF.
    392 
    393  DEFAULT(R"(
    394 pref)",
    395    "test:2: prefs parse error: expected '(' after pref specifier\n"
    396  );
    397 
    398  DEFAULT(R"(
    399 pref()",
    400    "test:2: prefs parse error: expected pref name after '('\n"
    401  );
    402 
    403  DEFAULT(R"(
    404 pref("parse.error")",
    405    "test:2: prefs parse error: expected ',' after pref name\n"
    406  );
    407 
    408  DEFAULT(R"(
    409 pref("parse.error",)",
    410    "test:2: prefs parse error: expected pref value after ','\n"
    411  );
    412 
    413  DEFAULT(R"(
    414 pref("parse.error", -)",
    415    "test:2: prefs parse error: expected integer literal after '-'\n"
    416  );
    417 
    418  DEFAULT(R"(
    419 pref("parse.error", +)",
    420    "test:2: prefs parse error: expected integer literal after '+'\n"
    421  );
    422 
    423  DEFAULT(R"(
    424 pref("parse.error", true)",
    425    "test:2: prefs parse error: expected ',' or ')' after pref value\n"
    426  );
    427 
    428  USER(R"(
    429 user_pref("parse.error", true)",
    430    "test:2: prefs parse error: expected ')' after pref value\n"
    431  );
    432 
    433  DEFAULT(R"(
    434 pref("parse.error", true,)",
    435    "test:2: prefs parse error: expected pref attribute after ','\n"
    436  );
    437 
    438  DEFAULT(R"(
    439 pref("parse.error", true, sticky)",
    440    "test:2: prefs parse error: expected ',' or ')' after pref attribute\n"
    441  );
    442 
    443  DEFAULT(R"(
    444 pref("parse.error", true))",
    445    "test:2: prefs parse error: expected ';' after ')'\n"
    446  );
    447 
    448  // This is something we saw in practice with the old parser, which allowed
    449  // repeated semicolons.
    450  DEFAULT(R"(
    451 pref("parse.error", true);;
    452 pref("parse.error", true, locked);;;
    453 pref("parse.error", true, sticky, locked);;;;
    454 pref("int.ok", 0);
    455    )",
    456    "test:2: prefs parse error: expected pref specifier at start of pref definition\n"
    457    "test:3: prefs parse error: expected pref specifier at start of pref definition\n"
    458    "test:3: prefs parse error: expected pref specifier at start of pref definition\n"
    459    "test:4: prefs parse error: expected pref specifier at start of pref definition\n"
    460    "test:4: prefs parse error: expected pref specifier at start of pref definition\n"
    461    "test:4: prefs parse error: expected pref specifier at start of pref definition\n"
    462  );
    463 
    464  //-------------------------------------------------------------------------
    465  // Invalid syntax after various newline combinations, for the purpose of
    466  // testing that line numbers are correct.
    467  //-------------------------------------------------------------------------
    468 
    469  // In all of the following we have a \n, a \r, a \r\n, and then an error, so
    470  // the error is on line 4. (Note: these ones don't use raw string literals
    471  // because MSVC somehow swallows any \r that appears in them.)
    472 
    473  DEFAULT("\n \r \r\n bad",
    474    "test:4: prefs parse error: unknown keyword\n"
    475  );
    476 
    477  DEFAULT("#\n#\r#\r\n bad",
    478    "test:4: prefs parse error: unknown keyword\n"
    479  );
    480 
    481  DEFAULT("//\n//\r//\r\n bad",
    482    "test:4: prefs parse error: unknown keyword\n"
    483  );
    484 
    485  DEFAULT("/*\n \r \r\n*/ bad",
    486    "test:4: prefs parse error: unknown keyword\n"
    487  );
    488 
    489  // Note: the escape sequences do *not* affect the line number.
    490  DEFAULT("pref(\"foo\\n\n foo\\r\r foo\\r\\n\r\n foo\", bad);",
    491    "test:4: prefs parse error: unknown keyword\n"
    492  );
    493 
    494  // clang-format on
    495 }