From c70395fbdb27f20b97b0dc8d47fadad474eaaf04 Mon Sep 17 00:00:00 2001 From: Tom Date: Thu, 16 Apr 2020 16:10:03 +0100 Subject: [PATCH] [feaLib] Raise exception when GSUB statement doesn't match a rule. (#1876) * [feaLib] Raise exception when substitute statement doesnt match any of the rules. Add tests that trigger said exception. --- Lib/fontTools/feaLib/parser.py | 8 +++++++- Tests/feaLib/data/GSUB_error.fea | 13 +++++++++++++ Tests/feaLib/parser_test.py | 7 +++++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 Tests/feaLib/data/GSUB_error.fea diff --git a/Lib/fontTools/feaLib/parser.py b/Lib/fontTools/feaLib/parser.py index bda34e261..1008f16a3 100644 --- a/Lib/fontTools/feaLib/parser.py +++ b/Lib/fontTools/feaLib/parser.py @@ -826,8 +826,14 @@ class Parser(object): 'is not supported', location) + # If there are remaining glyphs to parse, this is an invalid GSUB statement + if len(new) != 0: + raise FeatureLibError( + 'Invalid substitution statement', + location + ) + # GSUB lookup type 6: Chaining contextual substitution. - assert len(new) == 0, new rule = self.ast.ChainContextSubstStatement( old_prefix, old, old_suffix, lookups, location=location) return rule diff --git a/Tests/feaLib/data/GSUB_error.fea b/Tests/feaLib/data/GSUB_error.fea new file mode 100644 index 000000000..ae175c501 --- /dev/null +++ b/Tests/feaLib/data/GSUB_error.fea @@ -0,0 +1,13 @@ +# Trigger a parser error in the function parse_substitute_ in order to improve the error message. +# Note that this is not a valid substitution, this test is made to trigger an error. + +languagesystem latn dflt; + +@base = [a e]; +@accents = [acute grave]; + +feature abvs { + lookup lookup1 { + sub @base @accents by @base; + } lookup1; +} abvs; diff --git a/Tests/feaLib/parser_test.py b/Tests/feaLib/parser_test.py index cb4e689b7..f2256b4c4 100644 --- a/Tests/feaLib/parser_test.py +++ b/Tests/feaLib/parser_test.py @@ -1502,6 +1502,13 @@ class ParserTest(unittest.TestCase): FeatureLibError, 'Expected "by", "from" or explicit lookup references', self.parse, "feature liga {substitute f f i;} liga;") + + def test_substitute_invalid_statement(self): + self.assertRaisesRegex( + FeatureLibError, + "Invalid substitution statement", + Parser(self.getpath("GSUB_error.fea"), GLYPHNAMES).parse + ) def test_subtable(self): doc = self.parse("feature test {subtable;} test;")