gecko-dev/toolkit
Nicholas Nethercote 67e80b725b Bug 1423840 - Rewrite the prefs parser. r=glandium,Manishearth
The prefs parser has two significant problems.

- It doesn't separate tokenizing from parsing.

- It is implemented as a loop around a big switch on a "current state"
  variable.

As a result, it is hard to understand and modify, slower than it could be, and
in obscure cases (involving comments and whitespace) it fails to parse what
should be valid input.

This patch replaces it with a recursive descent parser (albeit one without any
recursion!) that has separate tokenization. The new parser is easier to
understand and modify, more correct, and has better error messages. It doesn't
do error recovery, but that would be much easier to add than in the old parser.

The new parser also runs about 1.9x faster than the existing parser. (As
measured by parsing greprefs.js's contents from memory 1000 times in
succession, omitting the prefs hash table construction. If the table
construction is included, it's about 1.6x faster.)

The new parser is slightly stricter than the old parser in a few ways.

- Disconcertingly, the old parser allowed arbitrary junk between prefs
  (including at the start and end of the prefs file) so long as that junk
  didn't include any of the following chars: '/', '#', 'u', 's', 'p'. I.e.
  lines like these:

    !foo@bar&pref("prefname", true);
    ticky_pref("prefname", true);       // missing 's' at start
    User_pref("prefname", true);        // should be 'u' at start

  would all be treated the same as this:

    pref("prefname", true);

  The new parser disallows such junk because it isn't necessary and seems like
  an unintentional botch by the old parser.

- The old parser allowed character 0x1a (SUB) between tokens and treated it
  like '\n'.

  The new parser does not allow this character. SUB was used to indicate
  end-of-file (*not* end-of-line) in some old operating systems such as MS-DOS,
  but this doesn't seem necessary today.

- The old parser tolerated (with a warning) invalid escape sequences within
  string literals -- such as "\q" (not a valid escape) and "\x1" and "\u12"
  (both of which have insufficient hex digits) -- accepting them literally.

  The new parser does not tolerate invalid escape sequences because it doesn't
  seem necessary and would complicate things.

- The old parser tolerated character 0x00 (NUL) within string literals; this is
  dangerous because C++ code that manipulates string values with embedded NULs
  will almost certainly consider those chars as end-of-string markers.

  The new parser treats NUL chars as end-of-file, to avoid this danger and
  because it facilitates a significant optimization (described within the
  code).

- The old parser allowed integer literals to overflow, silently wrapping them.

  The new parser treats integer overflow as a parse error. This seems better,
  and it caught an existing overflow in testing/profiles/prefs_general.js, for
  places.database.lastMaintenance (see bug 1424030).

The first of these changes meant that a couple of existing prefs with ";;" at
the end had to be changed (done in the preceding patch).

The minor increase in strictness shouldn't be a problem for default pref files
such as greprefs.js within the application (which we can modify), nor for
app-written prefs files such as prefs.js. It could affect user-written prefs
files such as user.js; the experience above suggests that ";;" is the most
likely problem in practice. In my opinion, the risk here is acceptable.

The new parser also does a better job of tracking line numbers because it (a)
treats "\r\n" sequences as a single end-of-line marker, and (a) pays attention
to end-of-line sequences within string literals.

Finally, the patch adds thorough tests of both valid and invalid syntax.

MozReview-Commit-ID: 8EYWH7KxGG
* * *
[mq]: win-fix

MozReview-Commit-ID: 91Bxjfghqfw

--HG--
extra : rebase_source : a8773413e5d68c33e4329df6819b6e1f82c22b85
2017-12-03 00:26:36 +11:00
..
components Merge mozilla-central to inbound. a=merge CLOSED TREE 2018-02-01 00:38:55 +02:00
content Merge mozilla-central to inbound. a=merge CLOSED TREE 2018-02-01 00:38:55 +02:00
crashreporter Bug 1431533: Part 5a - Auto-rewrite code to use ChromeUtils import methods. r=florian 2018-01-29 15:20:18 -08:00
forgetaboutsite Bug 1431533: Part 5a - Auto-rewrite code to use ChromeUtils import methods. r=florian 2018-01-29 15:20:18 -08:00
library Bug 1423840 - Rewrite the prefs parser. r=glandium,Manishearth 2017-12-03 00:26:36 +11:00
locales Add tiling and paint worker count information to about:support. (bug 1432516, r=milan) 2018-01-23 15:52:13 -06:00
modules Backed out 8 changesets (bug 633062) as requested by eoger on a CLOSED TREE 2018-01-31 22:09:30 +02:00
mozapps merge mozilla-inbound to mozilla-central. r=merge a=merge 2018-01-31 00:22:27 +02:00
pluginproblem Bug 1409148 - Add dynamic sizing on the plugin overlay. r=dthayer,johannh 2017-11-10 14:05:04 -02:00
profile Bug 1431533: Part 5a - Auto-rewrite code to use ChromeUtils import methods. r=florian 2018-01-29 15:20:18 -08:00
system Bug 1411579 - add system handler when Firefox runs in flatpak; r=stransky 2018-01-12 16:32:53 +01:00
themes Backed out changeset 834045a73734 (bug 1432630) for causing bug 1434153 on a CLOSED TREE 2018-01-30 13:50:43 +02:00
xre Bug 1431533: Part 5a - Auto-rewrite code to use ChromeUtils import methods. r=florian 2018-01-29 15:20:18 -08:00
.eslintrc.js Bug 1421968 - Enable ESLint rule mozilla/use-services by default, but whitelist it for various directories still to be fixed. r=mossop 2017-11-28 19:24:12 +00:00
moz.build Bug 1278282 - update of the moz.build files to remove gtk2 references r=lsalzman 2018-01-10 10:04:59 +01:00
moz.configure Bug 1433775 - Add Linux/arm support to Gecko Profiler. r=mstange 2018-01-29 18:01:23 +09:00
nss.configure
toolkit.mozbuild Backed out 5 changesets (bug 1418425) requested per comment #83. on a CLOSED TREE a=backout 2018-01-15 15:30:30 +02:00