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:
parent
baa4cee70c
commit
4e5a8fac4a
|
@ -36,6 +36,14 @@ def grouped(iterable, n):
|
||||||
return zip(*[iter(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 = {
|
typeBits = {
|
||||||
'CHAR': None,
|
'CHAR': None,
|
||||||
'SHORT': None,
|
'SHORT': None,
|
||||||
|
@ -46,6 +54,10 @@ typeBits = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def isUnsignedType(ty):
|
||||||
|
return ty == 'unsigned' or ty.startswith('uint')
|
||||||
|
|
||||||
|
|
||||||
def simpleMatch(token, pattern):
|
def simpleMatch(token, pattern):
|
||||||
for p in pattern.split(' '):
|
for p in pattern.split(' '):
|
||||||
if not token or token.str != p:
|
if not token or token.str != p:
|
||||||
|
@ -274,9 +286,7 @@ C99_STDLIB_IDENTIFIERS = {
|
||||||
'UINTMAX_MAX', 'PTRDIFF_MIN', 'PTRDIFF_MAX', 'SIG_ATOMIC_MIN',
|
'UINTMAX_MAX', 'PTRDIFF_MIN', 'PTRDIFF_MAX', 'SIG_ATOMIC_MIN',
|
||||||
'SIG_ATOMIC_MAX', 'SIZE_MAX', 'WCHAR_MIN', 'WCHAR_MAX', 'WINT_MIN',
|
'SIG_ATOMIC_MAX', 'SIZE_MAX', 'WCHAR_MIN', 'WCHAR_MAX', 'WINT_MIN',
|
||||||
'WINT_MAX', 'INTN_C', 'UINTN_C', 'INTMAX_C', 'UINTMAX_C',
|
'WINT_MAX', 'INTN_C', 'UINTN_C', 'INTMAX_C', 'UINTMAX_C',
|
||||||
] + ['%s%d_t' % (n, v) for n,v in itertools.product(
|
] + STDINT_TYPES,
|
||||||
['int', 'uint', 'int_least', 'uint_least', 'int_fast', 'uint_fast'],
|
|
||||||
[8, 16,32,64])],
|
|
||||||
# B.18 Input/output
|
# B.18 Input/output
|
||||||
'stdio.h': C90_STDLIB_IDENTIFIERS['stdio.h'] + [
|
'stdio.h': C90_STDLIB_IDENTIFIERS['stdio.h'] + [
|
||||||
'mode', 'restrict', 'snprintf', 'vfscanf', 'vscanf',
|
'mode', 'restrict', 'snprintf', 'vfscanf', 'vscanf',
|
||||||
|
@ -417,7 +427,7 @@ def getEssentialType(expr):
|
||||||
if expr.variable:
|
if expr.variable:
|
||||||
typeToken = expr.variable.typeStartToken
|
typeToken = expr.variable.typeStartToken
|
||||||
while typeToken and typeToken.isName:
|
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
|
return typeToken.str
|
||||||
typeToken = typeToken.next
|
typeToken = typeToken.next
|
||||||
|
|
||||||
|
@ -431,15 +441,10 @@ def getEssentialType(expr):
|
||||||
e2 = getEssentialType(expr.astOperand2)
|
e2 = getEssentialType(expr.astOperand2)
|
||||||
if not e1 or not e2:
|
if not e1 or not e2:
|
||||||
return None
|
return None
|
||||||
types = ['bool', 'char', 'short', 'int', 'long', 'long long']
|
if bitsOfEssentialType(e2) >= bitsOfEssentialType(e1):
|
||||||
try:
|
return e2
|
||||||
i1 = types.index(e1)
|
else:
|
||||||
i2 = types.index(e2)
|
return e1
|
||||||
if i2 >= i1:
|
|
||||||
return types[i2]
|
|
||||||
return types[i1]
|
|
||||||
except ValueError:
|
|
||||||
return None
|
|
||||||
elif expr.str == "~":
|
elif expr.str == "~":
|
||||||
e1 = getEssentialType(expr.astOperand1)
|
e1 = getEssentialType(expr.astOperand1)
|
||||||
return e1
|
return e1
|
||||||
|
@ -447,20 +452,22 @@ def getEssentialType(expr):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def bitsOfEssentialType(expr):
|
def bitsOfEssentialType(ty):
|
||||||
type = getEssentialType(expr)
|
if ty is None:
|
||||||
if type is None:
|
|
||||||
return 0
|
return 0
|
||||||
if type == 'char':
|
if ty == 'char':
|
||||||
return typeBits['CHAR']
|
return typeBits['CHAR']
|
||||||
if type == 'short':
|
if ty == 'short':
|
||||||
return typeBits['SHORT']
|
return typeBits['SHORT']
|
||||||
if type == 'int':
|
if ty == 'int':
|
||||||
return typeBits['INT']
|
return typeBits['INT']
|
||||||
if type == 'long':
|
if ty == 'long':
|
||||||
return typeBits['LONG']
|
return typeBits['LONG']
|
||||||
if type == 'long long':
|
if ty == 'long long':
|
||||||
return typeBits['LONG_LONG']
|
return typeBits['LONG_LONG']
|
||||||
|
for sty in STDINT_TYPES:
|
||||||
|
if ty == sty:
|
||||||
|
return int(''.join(filter(str.isdigit, sty)))
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
@ -1335,9 +1342,9 @@ class MisraChecker:
|
||||||
if not e1 or not e2:
|
if not e1 or not e2:
|
||||||
continue
|
continue
|
||||||
if token.str in ('<<', '>>'):
|
if token.str in ('<<', '>>'):
|
||||||
if e1 != 'unsigned':
|
if not isUnsignedType(e1):
|
||||||
self.reportError(token, 10, 1)
|
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)
|
self.reportError(token, 10, 1)
|
||||||
elif token.str in ('~', '&', '|', '^'):
|
elif token.str in ('~', '&', '|', '^'):
|
||||||
e1_et = getEssentialType(token.astOperand1)
|
e1_et = getEssentialType(token.astOperand1)
|
||||||
|
@ -1392,16 +1399,13 @@ class MisraChecker:
|
||||||
if not vt2 or vt2.pointer > 0:
|
if not vt2 or vt2.pointer > 0:
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
intTypes = ['char', 'short', 'int', 'long', 'long long']
|
|
||||||
index1 = intTypes.index(vt1.type)
|
|
||||||
if isCast(token.astOperand2):
|
if isCast(token.astOperand2):
|
||||||
e = vt2.type
|
e = vt2.type
|
||||||
else:
|
else:
|
||||||
e = getEssentialType(token.astOperand2)
|
e = getEssentialType(token.astOperand2)
|
||||||
if not e:
|
if not e:
|
||||||
continue
|
continue
|
||||||
index2 = intTypes.index(e)
|
if bitsOfEssentialType(vt1.type) > bitsOfEssentialType(e):
|
||||||
if index1 > index2:
|
|
||||||
self.reportError(token, 10, 6)
|
self.reportError(token, 10, 6)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
@ -1431,13 +1435,10 @@ class MisraChecker:
|
||||||
self.reportError(token, 10, 8)
|
self.reportError(token, 10, 8)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
intTypes = ['char', 'short', 'int', 'long', 'long long']
|
|
||||||
index1 = intTypes.index(token.valueType.type)
|
|
||||||
e = getEssentialType(token.astOperand1)
|
e = getEssentialType(token.astOperand1)
|
||||||
if not e:
|
if not e:
|
||||||
continue
|
continue
|
||||||
index2 = intTypes.index(e)
|
if bitsOfEssentialType(token.valueType.type) > bitsOfEssentialType(e):
|
||||||
if index1 > index2:
|
|
||||||
self.reportError(token, 10, 8)
|
self.reportError(token, 10, 8)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
@ -1625,7 +1626,7 @@ class MisraChecker:
|
||||||
maxval = val.intvalue
|
maxval = val.intvalue
|
||||||
if maxval == 0:
|
if maxval == 0:
|
||||||
continue
|
continue
|
||||||
sz = bitsOfEssentialType(token.astOperand1)
|
sz = bitsOfEssentialType(getEssentialType(token.astOperand1))
|
||||||
if sz <= 0:
|
if sz <= 0:
|
||||||
continue
|
continue
|
||||||
if maxval >= sz:
|
if maxval >= sz:
|
||||||
|
|
|
@ -267,7 +267,7 @@ void misra_10_1_ternary()
|
||||||
int8_t i8;
|
int8_t i8;
|
||||||
int16_t i16;
|
int16_t i16;
|
||||||
|
|
||||||
a = ui16 << ui16;
|
a = ui16 << ui16; // 10.6
|
||||||
a = ui16 << (get_bool(42) ? ui16 : ui16);
|
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) ? ui16 : (get_bool(34) ? ui16 : ui16)); // 10.4
|
||||||
a = ui16 << (get_bool(42) ? (get_bool(34) ? ui16 : 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
|
u32 c = ( u16) ( u32 a + u32 b ); //10.6
|
||||||
s32 i = c1 - c2; // FIXME: False positive for 10.6 (this is compliant). Trac #9488
|
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) {
|
void misra_10_8(u8 x, s32 a, s32 b) {
|
||||||
y = (u16)x;
|
y = (u16)x;
|
||||||
|
|
Loading…
Reference in New Issue