diff --git a/contrib/ci/check-null-false-returns.py b/contrib/ci/check-null-false-returns.py index a57926657..7502aa36d 100755 --- a/contrib/ci/check-null-false-returns.py +++ b/contrib/ci/check-null-false-returns.py @@ -1,5 +1,6 @@ #!/usr/bin/python3 -# pylint: disable=invalid-name,missing-docstring,too-many-branches,too-many-statements +# pylint: disable=invalid-name,missing-docstring,too-many-branches +# pylint: disable=too-many-statements,too-many-return-statements,too-few-public-methods # # Copyright (C) 2021 Richard Hughes # @@ -7,158 +8,228 @@ import glob import sys +from typing import List -def parse_rvif(line): +def _tokenize(line: str) -> List[str]: # remove whitespace + line = line.strip() line = line.replace("\t", "") - line = line.replace(" ", "") + line = line.replace(";", "") # find value + line = line.replace(" ", "|") line = line.replace(",", "|") line = line.replace(")", "|") - return line.rsplit("|", maxsplit=2)[1] + line = line.replace("(", "|") + + # return empty tokens + tokens = [] + for token in line.rsplit("|"): + if token: + tokens.append(token) + return tokens -def test_rvif(fn, line_num, valid_values, line): +class ReturnValidator: + def __init__(self): + self.warnings: List[str] = [] - # parse "g_return_val_if_fail (SOMETHING (foo), NULL)" - value = parse_rvif(line) + # internal state + self._fn = None + self._line_num = None + self._value = None + self._nret = None + self._rvif = None + self._line = None - # enumerated enum, so ignore - if value.find("_") != -1: - return True + @property + def _tokens(self) -> List[str]: + return _tokenize(self._line) - # convert alternate forms back to normal - if value in ["0x0", "0x00", "0x0000"]: - value = "0" - if value in ["0xffffffff"]: - value = "G_MAXUINT32" - if value in ["0xffff"]: - value = "G_MAXUINT16" - if value in ["0xff"]: - value = "G_MAXUINT8" - if value in ["G_SOURCE_REMOVE"]: - value = "FALSE" - if value in ["G_SOURCE_CONTINUE"]: - value = "TRUE" - if value not in valid_values: - print( - "{} line {} got {}, expected {}".format( - fn, line_num, value, ", ".join(valid_values) + @property + def _value_relaxed(self) -> str: + if self._value in ["0x0", "0x00", "0x0000"]: + return "0" + if self._value in ["0xffffffff"]: + return "G_MAXUINT32" + if self._value in ["0xffff"]: + return "G_MAXUINT16" + if self._value in ["0xff"]: + return "G_MAXUINT8" + if self._value in ["G_SOURCE_REMOVE"]: + return "FALSE" + if self._value in ["G_SOURCE_CONTINUE"]: + return "TRUE" + return self._value + + def _test_rvif(self) -> None: + + # parse "g_return_val_if_fail (SOMETHING (foo), NULL);" + self._value = self._tokens[-1] + + # enumerated enum, so ignore + if self._value.find("_") != -1: + return + + # is invalid + if self._rvif and self._value_relaxed not in self._rvif: + self.warnings.append( + "{} line {} got {}, expected {}".format( + self._fn, self._line_num, self._value, ", ".join(self._rvif) + ) ) - ) - return False - # success - return True + def _test_return(self) -> None: + # parse "return 0x0;" + self._value = self._tokens[-1] -def test_file(fn): - allokay = True - with open(fn) as f: - valid_values = None - line_num = 0 - for line in f.readlines(): - line_num += 1 - line = line.rstrip() - if not line: - continue - idx = line.find("g_return_val_if_fail") - if idx != -1 and valid_values: - if not test_rvif(fn, line_num, valid_values, line): - allokay = False - continue + # is invalid + if self._nret and self._value_relaxed in self._nret: + self.warnings.append( + "{} line {} got {}, which is not valid".format( + self._fn, self._line_num, self._value + ) + ) - # not a function header - if line[0] in ["#", " ", "\t", "{", "}", "/"]: - continue + def parse(self, fn: str) -> None: - # label - if line.endswith(":"): - continue + self._fn = fn + with open(fn) as f: + self._rvif = None + self._nret = None + self._line_num = 0 + for line in f.readlines(): + self._line_num += 1 + line = line.rstrip() + if not line: + continue + if line.endswith("\\"): + continue + if line.endswith("&&"): + continue + self._line = line + idx = line.find("g_return_val_if_fail") + if idx != -1: + self._test_rvif() + continue + idx = line.find("return") + if idx != -1: + # continue + if len(self._tokens) == 2: + self._test_return() + continue - # remove static prefix - if line.startswith("static"): - line = line[7:] + # not a function header + if line[0] in ["#", " ", "\t", "{", "}", "/"]: + continue - # a pointer - if line.endswith("*"): - valid_values = ["NULL"] - continue + # label + if line.endswith(":"): + continue - # not a leading line - if line.find(" ") != -1: - continue + # remove prefixes + if line.startswith("static"): + line = line[7:] + if line.startswith("inline"): + line = line[7:] - # a type we know - if line in ["void"]: - valid_values = [] - continue - if line in ["gpointer"]: - valid_values = ["NULL"] - continue - if line in ["gboolean"]: - valid_values = ["TRUE", "FALSE"] - continue - if line in ["guint32"]: - valid_values = ["0", "G_MAXUINT32"] - continue - if line in ["GQuark", "GType"]: - valid_values = ["0"] - continue - if line in ["guint64"]: - valid_values = ["0", "G_MAXUINT64"] - continue - if line in ["guint16"]: - valid_values = ["0", "G_MAXUINT16"] - continue - if line in ["guint8"]: - valid_values = ["0", "G_MAXUINT8"] - continue - if line in ["gint64"]: - valid_values = ["0", "-1", "G_MAXINT64"] - continue - if line in ["gint32"]: - valid_values = ["0", "-1", "G_MAXINT32"] - continue - if line in ["gint16"]: - valid_values = ["0", "-1", "G_MAXINT16"] - continue - if line in ["gint8"]: - valid_values = ["0", "-1", "G_MAXINT8"] - continue - if line in ["gint", "int"]: - valid_values = ["0", "-1", "G_MAXINT"] - continue - if line in ["guint"]: - valid_values = ["0", "G_MAXUINT"] - continue - if line in ["gulong"]: - valid_values = ["0", "G_MAXLONG"] - continue - if line in ["gsize", "size_t"]: - valid_values = ["0", "G_MAXSIZE"] - continue - if line in ["gssize", "ssize_t"]: - valid_values = ["0", "-1", "G_MAXSSIZE"] - continue - # print('unknown return type {}'.format(line)) - valid_values = None + # a pointer + if line.endswith("*"): + self._rvif = ["NULL"] + self._nret = ["FALSE"] + continue - # global success - return allokay + # not a leading line + if line.find(" ") != -1: + continue + + # a type we know + if line in ["void"]: + self._rvif = [] + self._nret = [] + continue + if line in ["gpointer"]: + self._rvif = ["NULL"] + self._nret = ["FALSE"] + continue + if line in ["gboolean"]: + self._rvif = ["TRUE", "FALSE"] + self._nret = ["NULL", "0"] + continue + if line in ["guint32"]: + self._rvif = ["0", "G_MAXUINT32"] + self._nret = ["NULL", "TRUE", "FALSE"] + continue + if line in ["GQuark", "GType"]: + self._rvif = ["0"] + self._nret = ["NULL", "0", "TRUE", "FALSE"] + continue + if line in ["guint64"]: + self._rvif = ["0", "G_MAXUINT64"] + self._nret = ["NULL", "TRUE", "FALSE"] + continue + if line in ["guint16"]: + self._rvif = ["0", "G_MAXUINT16"] + self._nret = ["NULL", "TRUE", "FALSE"] + continue + if line in ["guint8"]: + self._rvif = ["0", "G_MAXUINT8"] + self._nret = ["NULL", "TRUE", "FALSE"] + continue + if line in ["gint64"]: + self._rvif = ["0", "-1", "G_MAXINT64"] + self._nret = ["NULL", "TRUE", "FALSE"] + continue + if line in ["gint32"]: + self._rvif = ["0", "-1", "G_MAXINT32"] + self._nret = ["NULL", "TRUE", "FALSE"] + continue + if line in ["gint16"]: + self._rvif = ["0", "-1", "G_MAXINT16"] + self._nret = ["NULL", "TRUE", "FALSE"] + continue + if line in ["gint8"]: + self._rvif = ["0", "-1", "G_MAXINT8"] + self._nret = ["NULL", "TRUE", "FALSE"] + continue + if line in ["gint", "int"]: + self._rvif = ["0", "-1", "G_MAXINT"] + self._nret = ["NULL", "TRUE", "FALSE"] + continue + if line in ["guint"]: + self._rvif = ["0", "G_MAXUINT"] + self._nret = ["NULL", "TRUE", "FALSE"] + continue + if line in ["gulong"]: + self._rvif = ["0", "G_MAXLONG"] + self._nret = ["NULL", "TRUE", "FALSE"] + continue + if line in ["gsize", "size_t"]: + self._rvif = ["0", "G_MAXSIZE"] + self._nret = ["NULL", "TRUE", "FALSE"] + continue + if line in ["gssize", "ssize_t"]: + self._rvif = ["0", "-1", "G_MAXSSIZE"] + self._nret = ["NULL", "TRUE", "FALSE"] + continue + # print('unknown return type {}'.format(line)) + self._rvif = None + self._nret = None def test_files(): # test all C source files - rc = 0 + validator = ReturnValidator() for fn in glob.glob("**/*.c", recursive=True): - if not test_file(fn): - rc = 1 - return rc + validator.parse(fn) + for warning in validator.warnings: + print(warning) + + return 1 if validator.warnings else 0 if __name__ == "__main__": diff --git a/plugins/superio/fu-superio-device.c b/plugins/superio/fu-superio-device.c index 561e299be..0657aae2a 100644 --- a/plugins/superio/fu-superio-device.c +++ b/plugins/superio/fu-superio-device.c @@ -122,7 +122,7 @@ fu_superio_device_to_string (FuUdevDevice *device, guint idt, GString *str) fu_common_string_append_kx (str, idt, "PM1_IOBAD1", priv->pm1_iobad1); } -static guint16 +static gboolean fu_superio_device_check_id (FuSuperioDevice *self, GError **error) { FuSuperioDevicePrivate *priv = GET_PRIVATE (self);