misra.py: Handle stdint.h essential types (#2555)

Add stdint.h essential types to misra.py checks. This will fix false
negatives for rules 10.6 and 10.8.
This commit is contained in:
Georgy Komarov 2020-02-27 13:28:48 +03:00 committed by GitHub
parent baa4cee70c
commit 4e5a8fac4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 38 additions and 33 deletions

View File

@ -36,6 +36,14 @@ def grouped(iterable, n):
return zip(*[iter(iterable)] * n)
INT_TYPES = ['bool', 'char', 'short', 'int', 'long', 'long long']
STDINT_TYPES = ['%s%d_t' % (n, v) for n, v in itertools.product(
['int', 'uint', 'int_least', 'uint_least', 'int_fast', 'uint_fast'],
[8, 16, 32, 64])]
typeBits = {
'CHAR': None,
'SHORT': None,
@ -46,6 +54,10 @@ typeBits = {
}
def isUnsignedType(ty):
return ty == 'unsigned' or ty.startswith('uint')
def simpleMatch(token, pattern):
for p in pattern.split(' '):
if not token or token.str != p:
@ -274,9 +286,7 @@ C99_STDLIB_IDENTIFIERS = {
'UINTMAX_MAX', 'PTRDIFF_MIN', 'PTRDIFF_MAX', 'SIG_ATOMIC_MIN',
'SIG_ATOMIC_MAX', 'SIZE_MAX', 'WCHAR_MIN', 'WCHAR_MAX', 'WINT_MIN',
'WINT_MAX', 'INTN_C', 'UINTN_C', 'INTMAX_C', 'UINTMAX_C',
] + ['%s%d_t' % (n, v) for n,v in itertools.product(
['int', 'uint', 'int_least', 'uint_least', 'int_fast', 'uint_fast'],
[8, 16,32,64])],
] + STDINT_TYPES,
# B.18 Input/output
'stdio.h': C90_STDLIB_IDENTIFIERS['stdio.h'] + [
'mode', 'restrict', 'snprintf', 'vfscanf', 'vscanf',
@ -417,7 +427,7 @@ def getEssentialType(expr):
if expr.variable:
typeToken = expr.variable.typeStartToken
while typeToken and typeToken.isName:
if typeToken.str in ('char', 'short', 'int', 'long', 'float', 'double'):
if typeToken.str in INT_TYPES + STDINT_TYPES + ['float', 'double']:
return typeToken.str
typeToken = typeToken.next
@ -431,15 +441,10 @@ def getEssentialType(expr):
e2 = getEssentialType(expr.astOperand2)
if not e1 or not e2:
return None
types = ['bool', 'char', 'short', 'int', 'long', 'long long']
try:
i1 = types.index(e1)
i2 = types.index(e2)
if i2 >= i1:
return types[i2]
return types[i1]
except ValueError:
return None
if bitsOfEssentialType(e2) >= bitsOfEssentialType(e1):
return e2
else:
return e1
elif expr.str == "~":
e1 = getEssentialType(expr.astOperand1)
return e1
@ -447,20 +452,22 @@ def getEssentialType(expr):
return None
def bitsOfEssentialType(expr):
type = getEssentialType(expr)
if type is None:
def bitsOfEssentialType(ty):
if ty is None:
return 0
if type == 'char':
if ty == 'char':
return typeBits['CHAR']
if type == 'short':
if ty == 'short':
return typeBits['SHORT']
if type == 'int':
if ty == 'int':
return typeBits['INT']
if type == 'long':
if ty == 'long':
return typeBits['LONG']
if type == 'long long':
if ty == 'long long':
return typeBits['LONG_LONG']
for sty in STDINT_TYPES:
if ty == sty:
return int(''.join(filter(str.isdigit, sty)))
return 0
@ -1335,9 +1342,9 @@ class MisraChecker:
if not e1 or not e2:
continue
if token.str in ('<<', '>>'):
if e1 != 'unsigned':
if not isUnsignedType(e1):
self.reportError(token, 10, 1)
elif e2 != 'unsigned' and not token.astOperand2.isNumber:
elif not isUnsignedType(e2) and not token.astOperand2.isNumber:
self.reportError(token, 10, 1)
elif token.str in ('~', '&', '|', '^'):
e1_et = getEssentialType(token.astOperand1)
@ -1392,16 +1399,13 @@ class MisraChecker:
if not vt2 or vt2.pointer > 0:
continue
try:
intTypes = ['char', 'short', 'int', 'long', 'long long']
index1 = intTypes.index(vt1.type)
if isCast(token.astOperand2):
e = vt2.type
else:
e = getEssentialType(token.astOperand2)
if not e:
continue
index2 = intTypes.index(e)
if index1 > index2:
if bitsOfEssentialType(vt1.type) > bitsOfEssentialType(e):
self.reportError(token, 10, 6)
except ValueError:
pass
@ -1431,13 +1435,10 @@ class MisraChecker:
self.reportError(token, 10, 8)
else:
try:
intTypes = ['char', 'short', 'int', 'long', 'long long']
index1 = intTypes.index(token.valueType.type)
e = getEssentialType(token.astOperand1)
if not e:
continue
index2 = intTypes.index(e)
if index1 > index2:
if bitsOfEssentialType(token.valueType.type) > bitsOfEssentialType(e):
self.reportError(token, 10, 8)
except ValueError:
pass
@ -1625,7 +1626,7 @@ class MisraChecker:
maxval = val.intvalue
if maxval == 0:
continue
sz = bitsOfEssentialType(token.astOperand1)
sz = bitsOfEssentialType(getEssentialType(token.astOperand1))
if sz <= 0:
continue
if maxval >= sz:

View File

@ -267,7 +267,7 @@ void misra_10_1_ternary()
int8_t i8;
int16_t i16;
a = ui16 << ui16;
a = ui16 << ui16; // 10.6
a = ui16 << (get_bool(42) ? ui16 : ui16);
a = ui16 << (get_bool(42) ? ui16 : (get_bool(34) ? ui16 : ui16)); // 10.4
a = ui16 << (get_bool(42) ? (get_bool(34) ? ui16 : ui16) : ui16); // 10.4
@ -305,6 +305,10 @@ void misra_10_6(u8 x, u32 a, u32 b, char c1, char c2) {
u32 c = ( u16) ( u32 a + u32 b ); //10.6
s32 i = c1 - c2; // FIXME: False positive for 10.6 (this is compliant). Trac #9488
}
void misra_10_6_1(uint32_t *a, uint16_t b, uint16_t c)
{
*a = b + c ; // 10.6
}
void misra_10_8(u8 x, s32 a, s32 b) {
y = (u16)x;