Bug 1434765 - Properly reject invalid variables in #if{,n}def. r?build
The invalid variable test for #if{,n}def was only checking that the
first character in the variable was alphanumeric or underscore, not
the other characters.
More generally, preprocessor instructions were also cut out such that
whitespaces before and after arguments were part of the arguments.
Subtly, some legitimate strings end with what, in ISO-8859-1, is
considered as whitespaces, and because the preprocessor largely works
on byte strings (str), and because the regexps are using re.U, those
characters (e.g. 0xa0) that can legitimately appear in byte strings of
UTF-8 encoding, are treated as whitespaces. So we remove the re.U from
the instruction regexp, so that only plain ascii whitespaces only are
stripped out.
There's one place in layout/tools/reftest/manifest.jsm that was using
a broken pattern, making the test never true, which, once fixed, unveils
broken tests, so the branch that was never used is removed.
--- a/layout/tools/reftest/manifest.jsm
+++ b/layout/tools/reftest/manifest.jsm
@@ -555,22 +555,17 @@ sandbox.compareRetainedDisplayLists = g.
}
sandbox.stylo = styloEnabled && !g.compareStyloToGecko;
sandbox.styloVsGecko = g.compareStyloToGecko;
#else
sandbox.stylo = false;
sandbox.styloVsGecko = false;
#endif
-// Printing via Skia PDF is only supported on Mac for now.
-#ifdef XP_MACOSX && MOZ_ENABLE_SKIA_PDF
- sandbox.skiaPdf = true;
-#else
sandbox.skiaPdf = false;
-#endif
#ifdef RELEASE_OR_BETA
sandbox.release_or_beta = true;
#else
sandbox.release_or_beta = false;
#endif
var hh = CC[NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX + "http"].
--- a/python/mozbuild/mozbuild/preprocessor.py
+++ b/python/mozbuild/mozbuild/preprocessor.py
@@ -334,19 +334,18 @@ class Preprocessor:
def setMarker(self, aMarker):
"""
Set the marker to be used for processing directives.
Used for handling CSS files, with pp.setMarker('%'), for example.
The given marker may be None, in which case no markers are processed.
"""
self.marker = aMarker
if aMarker:
- self.instruction = re.compile('{0}(?P<cmd>[a-z]+)(?:\s(?P<args>.*))?$'
- .format(aMarker),
- re.U)
+ self.instruction = re.compile('{0}(?P<cmd>[a-z]+)(?:\s+(?P<args>.*?))?\s*$'
+ .format(aMarker))
self.comment = re.compile(aMarker, re.U)
else:
class NoMatch(object):
def match(self, *args):
return False
self.instruction = self.comment = NoMatch()
def setSilenceDirectiveWarnings(self, value):
@@ -601,32 +600,32 @@ class Preprocessor:
self.ifStates[-1] = self.disableLevel
else:
self.ifStates.append(self.disableLevel)
pass
def do_ifdef(self, args, replace=False):
if self.disableLevel and not replace:
self.disableLevel += 1
return
- if re.match('\W', args, re.U):
+ if re.search('\W', args, re.U):
raise Preprocessor.Error(self, 'INVALID_VAR', args)
if args not in self.context:
self.disableLevel = 1
if replace:
if args in self.context:
self.disableLevel = 0
self.ifStates[-1] = self.disableLevel
else:
self.ifStates.append(self.disableLevel)
pass
def do_ifndef(self, args, replace=False):
if self.disableLevel and not replace:
self.disableLevel += 1
return
- if re.match('\W', args, re.U):
+ if re.search('\W', args, re.U):
raise Preprocessor.Error(self, 'INVALID_VAR', args)
if args in self.context:
self.disableLevel = 1
if replace:
if args not in self.context:
self.disableLevel = 0
self.ifStates[-1] = self.disableLevel
else:
--- a/python/mozbuild/mozbuild/test/test_preprocessor.py
+++ b/python/mozbuild/mozbuild/test/test_preprocessor.py
@@ -637,10 +637,29 @@ class TestPreprocessor(unittest.TestCase
self.pp.do_include('f')
self.assertEqual(self.pp.out.getvalue(), 'foobarbaz\n')
def test_command_line_literal_at(self):
with MockedOpen({"@foo@.in": '@foo@\n'}):
self.pp.handleCommandLine(['-Fsubstitution', '-Dfoo=foobarbaz', '@foo@.in'])
self.assertEqual(self.pp.out.getvalue(), 'foobarbaz\n')
+ def test_invalid_ifdef(self):
+ with MockedOpen({'dummy': '#ifdef FOO == BAR\nPASS\n#endif'}):
+ with self.assertRaises(Preprocessor.Error) as e:
+ self.pp.do_include('dummy')
+ self.assertEqual(e.exception.key, 'INVALID_VAR')
+
+ with MockedOpen({'dummy': '#ifndef FOO == BAR\nPASS\n#endif'}):
+ with self.assertRaises(Preprocessor.Error) as e:
+ self.pp.do_include('dummy')
+ self.assertEqual(e.exception.key, 'INVALID_VAR')
+
+ # Trailing whitespaces, while not nice, shouldn't be an error.
+ self.do_include_pass([
+ '#ifndef FOO ',
+ 'PASS',
+ '#endif',
+ ])
+
+
if __name__ == '__main__':
main()