fix crash while checking misra_9 when initializing a union with {{0,0}} (#5250)

This fixes a crash with following error:
```
Traceback (most recent call last):
  File "/usr/local/share/Cppcheck/addons/runaddon.py", line 8, in <module>
    runpy.run_path(addon, run_name='__main__')
  File "<frozen runpy>", line 291, in run_path
  File "<frozen runpy>", line 98, in _run_module_code
  File "<frozen runpy>", line 88, in _run_code
  File "/usr/local/share/Cppcheck/addons/misra.py", line 4737, in <module>
    main()
  File "/usr/local/share/Cppcheck/addons/misra.py", line 4679, in main
    checker.parseDump(item)
  File "/usr/local/share/Cppcheck/addons/misra.py", line 4335, in parseDump
    self.executeCheck(902, self.misra_9_2, cfg)
  File "/usr/local/share/Cppcheck/addons/misra.py", line 4246, in executeCheck
    check_function(*args)
  File "/usr/local/share/Cppcheck/addons/misra.py", line 2104, in misra_9_2
    misra_9.misra_9_x(self, data, 902)
  File "/usr/local/share/Cppcheck/addons/misra_9.py", line 414, in misra_9_x
    parser.parseInitializer(ed, eq.astOperand2)
  File "/usr/local/share/Cppcheck/addons/misra_9.py", line 320, in parseInitializer
    child = self.root.getChildByValueElement(self.ed)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'getChildByValueElement'
```

A minimal example and testcase is added. 
The extra check for nextChild seems to fix it, however i did not read
the whole codebase, so maybe this creates other issues.

---------

Co-authored-by: Tim Blume <tbl@sevenstax-intern.de>
This commit is contained in:
Tim Blume 2023-08-31 09:38:03 +02:00 committed by GitHub
parent e7dd9cd793
commit b70e1df26c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 20 additions and 4 deletions

View File

@ -293,7 +293,7 @@ class InitializerParser:
# Fake dummy as nextChild (of current root) # Fake dummy as nextChild (of current root)
nextChild = dummyRoot nextChild = dummyRoot
if self.token.astOperand1: if nextChild and self.token.astOperand1:
self.root = nextChild self.root = nextChild
self.token = self.token.astOperand1 self.token = self.token.astOperand1
isFirstElement = True isFirstElement = True
@ -328,7 +328,7 @@ class InitializerParser:
self.ed.parent.initializeChildren() self.ed.parent.initializeChildren()
else: else:
if self.ed.parent != self.root: if self.root is not None and self.ed.parent != self.root:
# Check if token is correct value type for self.root.children[?] # Check if token is correct value type for self.root.children[?]
child = self.root.getChildByValueElement(self.ed) child = self.root.getChildByValueElement(self.ed)
if self.token.valueType: if self.token.valueType:
@ -458,7 +458,6 @@ def misra_9_x(self, data, rule, rawTokens = None):
# without it. # without it.
if ed.valueType is None and not variable.isArray: if ed.valueType is None and not variable.isArray:
continue 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

@ -0,0 +1,18 @@
union {
struct {
uint8_t a;
uint8_t b;
} a;
} bar;
struct foo {
uint8_t a;
union bar w;
uint8_t b;
};
struct foo asdf = {
0,
{{0,0}},
1
};

View File

@ -120,7 +120,6 @@ def test_rules_suppression(checker, capsys):
assert found is None, 'Unexptected output:\n' + captured assert found is None, 'Unexptected output:\n' + captured
dump_remove(src) dump_remove(src)
def test_arguments_regression(): def test_arguments_regression():
args_ok = ["-generate-table", args_ok = ["-generate-table",
"--rule-texts=./addons/test/assets/misra_rules_multiple_lines.txt", "--rule-texts=./addons/test/assets/misra_rules_multiple_lines.txt",