cert.py: Added INT-31-C check, ensure that integer conversions do not result in lost or misinterpreted data
This commit is contained in:
parent
93e5140945
commit
56ceb5a58c
|
@ -17,6 +17,12 @@ def reportError(token, severity, msg, id):
|
||||||
sys.stderr.write(
|
sys.stderr.write(
|
||||||
'[' + token.file + ':' + str(token.linenr) + '] (' + severity + '): ' + msg + ' [' + id + ']\n')
|
'[' + 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):
|
def isUnpackedStruct(var):
|
||||||
decl = var.typeStartToken
|
decl = var.typeStartToken
|
||||||
|
@ -49,6 +55,12 @@ def isBitwiseOp(token):
|
||||||
def isComparisonOp(token):
|
def isComparisonOp(token):
|
||||||
return token and (token.str in {'==', '!=', '>', '>=', '<', '<='})
|
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
|
# EXP42-C
|
||||||
# do not compare padding data
|
# do not compare padding data
|
||||||
|
@ -79,6 +91,38 @@ def exp46(data):
|
||||||
reportError(
|
reportError(
|
||||||
token, 'style', 'Bitwise operator is used with a Boolean-like operand', 'cert-EXP46-c')
|
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:]:
|
for arg in sys.argv[1:]:
|
||||||
print('Checking ' + arg + '...')
|
print('Checking ' + arg + '...')
|
||||||
data = cppcheckdata.parsedump(arg)
|
data = cppcheckdata.parsedump(arg)
|
||||||
|
@ -87,3 +131,4 @@ for arg in sys.argv[1:]:
|
||||||
print('Checking ' + arg + ', config "' + cfg.name + '"...')
|
print('Checking ' + arg + ', config "' + cfg.name + '"...')
|
||||||
exp42(cfg)
|
exp42(cfg)
|
||||||
exp46(cfg)
|
exp46(cfg)
|
||||||
|
int31(cfg, data.platform)
|
||||||
|
|
Loading…
Reference in New Issue