Fix issue where misra 9_x evaluation crashes on some undefined structs with nested initialisers (#3290)

This commit is contained in:
Ivar Andreas Bonsaksen 2021-06-04 17:19:40 +02:00 committed by GitHub
parent 486e440c4a
commit e3b7ceec7e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 23 additions and 14 deletions

View File

@ -87,7 +87,7 @@ class ElementDef:
if self.isFlexible: if self.isFlexible:
while len(self.children) <= index: while len(self.children) <= index:
createChild(self, self.flexibleToken, len(self.children)) createChild(self, self.flexibleToken, len(self.children))
return self.children[index] if index >= 0 and len(self.children) > index else None return self.children[index] if 0 <= index < len(self.children) else None
def getChildByName(self, name): def getChildByName(self, name):
for c in self.children: for c in self.children:
@ -130,7 +130,7 @@ class ElementDef:
def getChildByValueElement(self, ed): def getChildByValueElement(self, ed):
potentialChild = ed potentialChild = ed
while potentialChild and not potentialChild in self.children: while potentialChild and potentialChild not in self.children:
potentialChild = potentialChild.parent potentialChild = potentialChild.parent
return self.children[self.children.index(potentialChild)] if potentialChild else None return self.children[self.children.index(potentialChild)] if potentialChild else None
@ -197,8 +197,8 @@ class ElementDef:
def isMisra93Compliant(self): def isMisra93Compliant(self):
if self.elementType == 'array': if self.elementType == 'array':
result = self.isAllChildrenSet() or \ result = self.isAllChildrenSet() or \
((self.isAllSet() or \ ((self.isAllSet() or
self.isOnlyDesignated()) and \ self.isOnlyDesignated()) and
all([not (child.isDesignated or child.isPositional) or child.isMisra93Compliant() for child in self.children])) all([not (child.isDesignated or child.isPositional) or child.isMisra93Compliant() for child in self.children]))
return result return result
elif self.elementType == 'record': elif self.elementType == 'record':
@ -213,7 +213,7 @@ class ElementDef:
def isMisra95Compliant(self): def isMisra95Compliant(self):
return not self.isFlexible or all([not child.isDesignated for child in self.children]) return not self.isFlexible or all([not child.isDesignated for child in self.children])
# Parses the initializers and uodate the ElementDefs status accordingly # Parses the initializers and update the ElementDefs status accordingly
class InitializerParser: class InitializerParser:
def __init__(self): def __init__(self):
self.token = None self.token = None
@ -254,7 +254,7 @@ class InitializerParser:
isDesignated = True isDesignated = True
elif self.token.str == '{': elif self.token.str == '{':
nextChild = self.root.getNextChild() nextChild = self.root.getNextChild() if self.root is not None else None
if nextChild: if nextChild:
if nextChild.isArray or nextChild.isRecord: if nextChild.isArray or nextChild.isRecord:
@ -286,6 +286,7 @@ class InitializerParser:
self.token = self.token.astOperand1 self.token = self.token.astOperand1
isFirstElement = True isFirstElement = True
else: else:
if self.root:
# {} # {}
if self.root.name == '<-': if self.root.name == '<-':
self.root.parent.markStuctureViolation(self.token) self.root.parent.markStuctureViolation(self.token)
@ -403,6 +404,12 @@ def misra_9_x(self, data, rule, rawTokens = None):
if variable.isArray or variable.isClass: if variable.isArray or variable.isClass:
ed = getElementDef(nameToken, rawTokens) ed = getElementDef(nameToken, rawTokens)
# No need to check non-arrays if valueType is missing,
# since we can't say anything useful about the structure
# without it.
if ed.valueType is None and not variable.isArray:
continue
parser.parseInitializer(ed, eq.astOperand2) parser.parseInitializer(ed, eq.astOperand2)
# print(rule, nameToken.str + '=', ed.getInitDump()) # print(rule, nameToken.str + '=', ed.getInitDump())
if rule == 902 and not ed.isMisra92Compliant(): if rule == 902 and not ed.isMisra92Compliant():

View File

@ -479,7 +479,9 @@ void misra_9_struct_initializers(void) {
dummy_struct dsc[2][2] = { {1,2}, {3,4} }; dummy_struct dsc[2][2] = { {1,2}, {3,4} };
dummy_struct dsd[2][2] = { 1, 2, 3, 4 }; // 9.2 dummy_struct dsd[2][2] = { 1, 2, 3, 4 }; // 9.2
dummy_struct dse[3] = { {1,2}, {3,4}, [1] = {5,6} }; // 9.3 9.4 dummy_struct dse[3] = { {1,2}, {3,4}, [1] = {5,6} }; // 9.3 9.4
dummy_struct dsd[] = { [0] = 1 }; // 9.5 dummy_struct dsf[] = { [0] = 1 }; // 9.5
dummy_struct dsg = { .a = {0}, .b = {0} };
dummy_struct dsh[2][2] = { { {.a = 0, .b = {0}}, { 0 } }, { { 0 }, {.a = 0, .b = {0}}} };
// Obsolete initialization syntax for GCC // Obsolete initialization syntax for GCC
struct1 os1 = { i1: 1, i2: 2 }; // 10.4 13.4 struct1 os1 = { i1: 1, i2: 2 }; // 10.4 13.4