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)
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2020-07-17 11:09:31 +02:00
parent 457763aa03
commit 77547d5313
1 changed files with 24 additions and 2 deletions

View File

@ -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)