From 77547d5313ea916d2fb64ca5a8812734e9b50f92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Fri, 17 Jul 2020 11:09:31 +0200 Subject: [PATCH] hwdb: check that uppercase digits are used in modalias patterns This is all confusing as hell, becuase in some places lowercase hexadecimal digits are used, and in other places uppercase. This adds a check for the most common case that we and others got wrong. I tried to extend the general grammar in hwdb_grammar() to include this check, but it quickly became very complicated and didn't seem to work properly. Doing initial parsing with more general rules is easier and also seems to give better error messages: /home/zbyszek/src/systemd-work/build/../hwdb.d/60-autosuspend.hwdb: 3 match groups, 5 matches, 3 properties Pattern 'v058fp9540*' is invalid: Expected W:(0123...), found 'f' (at char 4), (line:1, col:5) --- hwdb.d/parse_hwdb.py | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/hwdb.d/parse_hwdb.py b/hwdb.d/parse_hwdb.py index c9851ca64c9..025133416f6 100755 --- a/hwdb.d/parse_hwdb.py +++ b/hwdb.d/parse_hwdb.py @@ -79,6 +79,9 @@ GENERAL_MATCHES = {'acpi', 'OUI', } +def upperhex_word(length): + return Word(nums + 'ABCDEF', exact=length) + @lru_cache() def hwdb_grammar(): ParserElement.setDefaultWhitespaceChars('') @@ -180,8 +183,27 @@ def parse(fname): return [] return [convert_properties(g) for g in parsed.GROUPS] -def check_match_uniqueness(groups): +def check_matches(groups): matches = sum((group[0] for group in groups), []) + + # This is a partial check. The other cases could be also done, but those + # two are most commonly wrong. + grammars = { 'usb' : 'v' + upperhex_word(4) + Optional('p' + upperhex_word(4)), + 'pci' : 'v' + upperhex_word(8) + Optional('d' + upperhex_word(8)), + } + + for match in matches: + prefix, rest = match.split(':', maxsplit=1) + gr = grammars.get(prefix) + if gr: + try: + gr.parseString(rest) + except ParseBaseException as e: + error('Pattern {!r} is invalid: {}', rest, e) + continue + if rest[-1] not in '*:': + error('pattern {} does not end with "*" or ":"', match) + matches.sort() prev = None for match in matches: @@ -256,7 +278,7 @@ if __name__ == '__main__': for fname in args: groups = parse(fname) print_summary(fname, groups) - check_match_uniqueness(groups) + check_matches(groups) check_properties(groups) sys.exit(ERROR)