diff --git a/addons/cert.py b/addons/cert.py index 939b64e96..0bdb32500 100644 --- a/addons/cert.py +++ b/addons/cert.py @@ -17,6 +17,12 @@ def reportError(token, severity, msg, id): sys.stderr.write( '[' + token.file + ':' + str(token.linenr) + '] (' + severity + '): ' + msg + ' [' + id + ']\n') +def simpleMatch(token, pattern): + for p in pattern.split(' '): + if not token or token.str != p: + return False + token = token.next + return True def isUnpackedStruct(var): decl = var.typeStartToken @@ -49,6 +55,12 @@ def isBitwiseOp(token): def isComparisonOp(token): return token and (token.str in {'==', '!=', '>', '>=', '<', '<='}) +def isCast(expr): + if not expr or expr.str != '(' or not expr.astOperand1 or expr.astOperand2: + return False + if simpleMatch(expr, '( )'): + return False + return True # EXP42-C # do not compare padding data @@ -79,6 +91,38 @@ def exp46(data): reportError( token, 'style', 'Bitwise operator is used with a Boolean-like operand', 'cert-EXP46-c') +# INT31-C +# Ensure that integer conversions do not result in lost or misinterpreted data +def int31(data, platform): + if not platform: + return + for token in data.tokenlist: + if not isCast(token): + continue + if not token.valueType or not token.astOperand1.values: + continue + bits = None + if token.valueType.type == 'char': + bits = platform.char_bit + elif token.valueType.type == 'short': + bits = platform.short_bit + elif token.valueType.type == 'int': + bits = platform.int_bit + elif token.valueType.type == 'long': + bits = platform.long_bit + else: + continue + if bits >= 64: + continue + maxval = (1 << (bits - 1) - 1) + for value in token.astOperand1.values: + if value.intvalue > maxval: + reportError( + token, + 'style', + 'Loss of information when casting ' + str(value.intvalue) + ' to ' + token.valueType.type, + 'cert-INT31-c') + for arg in sys.argv[1:]: print('Checking ' + arg + '...') data = cppcheckdata.parsedump(arg) @@ -87,3 +131,4 @@ for arg in sys.argv[1:]: print('Checking ' + arg + ', config "' + cfg.name + '"...') exp42(cfg) exp46(cfg) + int31(cfg, data.platform)