cert.py: Added INT-31-C check, ensure that integer conversions do not result in lost or misinterpreted data

This commit is contained in:
Daniel Marjamäki 2017-10-14 22:24:24 +02:00
parent 93e5140945
commit 56ceb5a58c
1 changed files with 45 additions and 0 deletions

View File

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