cert.py: Added testcases for EXP42 and fixed the code a little

This commit is contained in:
Daniel Marjamäki 2018-01-23 17:18:47 +01:00
parent d46cd46d0f
commit 8eae9cdd60
2 changed files with 52 additions and 28 deletions

View File

@ -30,28 +30,29 @@ def simpleMatch(token, pattern):
token = token.next token = token.next
return True return True
def isUnpackedStruct(var): def isUnpackedStruct(token):
decl = var.typeStartToken if token.valueType is None:
while decl and decl.isName: return False
if decl.str == 'struct': if token.valueType.typeScope is None:
structScope = decl.next.typeScope return False;
if structScope: if token.valueType.typeScope.type != "Struct":
linenr = int(structScope.classStart.linenr) return False
for line in open(structScope.classStart.file): startToken = token.valueType.typeScope.classStart
linenr = int(startToken.linenr)
for line in open(startToken.file):
linenr -= 1 linenr -= 1
if linenr == 0: if linenr == 0:
return True return True
if re.match(r'#pragma\s+pack\s*\(', line): if linenr < 3 and re.match(r'#pragma\s+pack\s*\(', line):
return False
break
decl = decl.next
return False return False
return True
def isLocalUnpackedStruct(arg): def isLocalUnpackedStruct(arg):
if arg and arg.str == '&' and not arg.astOperand2: if arg and arg.str == '&' and not arg.astOperand2:
arg = arg.astOperand1 arg = arg.astOperand1
return arg and arg.variable and (arg.variable.isLocal or arg.variable.isArgument) and isUnpackedStruct(arg.variable) return arg and arg.variable and (arg.variable.isLocal or arg.variable.isArgument) and isUnpackedStruct(arg)
def isBitwiseOp(token): def isBitwiseOp(token):
@ -72,7 +73,7 @@ def isCast(expr):
# do not compare padding data # do not compare padding data
def exp42(data): def exp42(data):
for token in data.tokenlist: for token in data.tokenlist:
if token.str != '(' or not token.astOperand1: if token.str != '(' or not token.astOperand1 or token.astOperand1.str != 'memcmp':
continue continue
arg1 = None arg1 = None
@ -82,7 +83,7 @@ def exp42(data):
arg1 = token.astOperand2.astOperand1.astOperand1 arg1 = token.astOperand2.astOperand1.astOperand1
arg2 = token.astOperand2.astOperand1.astOperand2 arg2 = token.astOperand2.astOperand1.astOperand2
if token.astOperand1.str == 'memcmp' and (isLocalUnpackedStruct(arg1) or isLocalUnpackedStruct(arg2)): if isLocalUnpackedStruct(arg1) or isLocalUnpackedStruct(arg2):
reportError( reportError(
token, 'style', "Comparison of struct padding data " + token, 'style', "Comparison of struct padding data " +
"(fix either by packing the struct using '#pragma pack' or by rewriting the comparison)", 'cert-EXP42-C') "(fix either by packing the struct using '#pragma pack' or by rewriting the comparison)", 'cert-EXP42-C')

View File

@ -1,7 +1,30 @@
// To test: // To test:
// ~/cppcheck/cppcheck --dump cert-test.c && python cert.py -verify cert-test.c.dump // ~/cppcheck/cppcheck --dump cert-test.c && python ../cert.py -verify cert-test.c.dump
unsigned char int31(int x) { struct S {
short a;
short b;
};
#pragma pack()
struct PackedStruct {
short a;
short b;
};
void exp42()
{
struct S s1 = {1,2};
struct S s2 = {1,2};
memcmp(&s1, &s2, sizeof(struct S)); // cert-EXP42-C
struct PackedStruct s3 = {1,2};
struct PackedStruct s4 = {1,2};
memcmp(&s3, &s4, sizeof(struct S));
}
unsigned char int31(int x)
{
x = (unsigned char)1000; // cert-INT31-c x = (unsigned char)1000; // cert-INT31-c
x = (signed char)0xff; // cert-INT31-c x = (signed char)0xff; // cert-INT31-c
x = (unsigned char)-1; // cert-INT31-c x = (unsigned char)-1; // cert-INT31-c