Skip to content

Commit

Permalink
Fix 9491: MISRA addon: False positive for rule 14.2 (loop counter ini…
Browse files Browse the repository at this point in the history
…tialized in function)
  • Loading branch information
swasti16 committed Oct 21, 2023
1 parent 67619bd commit f7b7237
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 9 deletions.
58 changes: 51 additions & 7 deletions addons/misra.py
Original file line number Diff line number Diff line change
Expand Up @@ -713,7 +713,29 @@ def getForLoopExpressions(forToken):
lpar.astOperand2.astOperand2.astOperand2]


def getForLoopCounterVariables(forToken):
def get_function_scope(cfg, func):
if func:
for scope in cfg.scopes:
if scope.function == func:
return scope
return None


def is_variable_changed(body_start, body_end, var):
"""Check if variable is updated between body_start and body_end"""
while body_start != body_end:
if not body_start.isAssignmentOp:
body_start = body_start.next
continue
tok = body_start
while tok.astOperand1:
if tok.astOperand1.variable == var:
return True
tok = tok.astOperand1
body_start = body_start.next
return False

def getForLoopCounterVariables(forToken, cfg):
""" Return a set of Variable objects defined in ``for`` statement and
satisfy requirements to loop counter term from section 8.14 of MISRA
document.
Expand Down Expand Up @@ -741,10 +763,31 @@ def getForLoopCounterVariables(forToken):
elif tn.previous and tn.previous.str in ('++', '--'):
vars_modified.add(tn.variable)
if cur_clause == 1 and tn.isAssignmentOp:
if tn.astOperand1.variable:
vars_initialized.add(tn.astOperand1.variable)
elif tn.astOperand1.str == "." and tn.astOperand1.astOperand2 and tn.astOperand1.astOperand2.variable:
vars_initialized.add(tn.astOperand1.astOperand2.variable)
var_token = tn.astOperand1
while var_token and var_token.str == '.':
var_token = var_token.astOperand2
if var_token and var_token.variable:
vars_initialized.add(var_token.variable)
if cur_clause == 1 and tn.function:
function_args_in_init = getArguments(tn.next);
function_args = tn.function.argument
function_scope = get_function_scope(cfg, tn.function)
for key, args in function_args.items():
if args.nameToken and args.nameToken.valueType and args.nameToken.valueType.pointer > 0:
function_body_start = None
function_body_end = None
if function_scope:
function_body_start = function_scope.bodyStart
function_body_end = function_scope.bodyEnd
if function_scope is None or \
(function_scope is not None and
is_variable_changed(function_body_start, function_body_end, args)):
arg_tok = function_args_in_init[int(key) - 1]
if arg_tok.variable:
vars_initialized.add(arg_tok.variable)
elif arg_tok.isOp and arg_tok.valueType and arg_tok.valueType.pointer > 0 \
and arg_tok.astOperand1.variable:
vars_initialized.add(arg_tok.astOperand1.variable)

if tn.str == ';':
cur_clause += 1
Expand Down Expand Up @@ -2768,13 +2811,14 @@ def misra_14_2(self, data):
if not expressions:
continue
if expressions[0] and not expressions[0].isAssignmentOp:
self.reportError(token, 14, 2)
if expressions[0].str != "(" or expressions[0].previous.function is None :
self.reportError(token, 14, 2)
if countSideEffectsRecursive(expressions[1]) > 0:
self.reportError(token, 14, 2)
if countSideEffectsRecursive(expressions[2]) > 1:
self.reportError(token, 14, 2)

counter_vars_first_clause, counter_vars_exit_modified = getForLoopCounterVariables(token)
counter_vars_first_clause, counter_vars_exit_modified = getForLoopCounterVariables(token, data)
if len(counter_vars_exit_modified) == 0:
# if it's not possible to identify a loop counter, all 3 clauses must be empty
for idx in range(len(expressions)):
Expand Down
8 changes: 6 additions & 2 deletions addons/test/misra/misra-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -1183,6 +1183,8 @@ static void misra_14_1(void) {
static void misra_14_2_init_value(int32_t *var) {
*var = 0;
}
static void misra_14_2_init_value_1(int32_t *var);

static void misra_14_2_fn1(bool b) {
for (;i++<10;) {} // 14.2
for (;i<10;dostuff()) {} // 14.2
Expand All @@ -1199,8 +1201,10 @@ static void misra_14_2_fn1(bool b) {
}
misra_14_2_init_value(&i2); // TODO: Fix false negative in function call
}

for (misra_14_2_init_value(&i); i < 10; ++i) {} // no-warning FIXME: False positive for 14.2 Trac #9491
int i1;
int i2;
for (misra_14_2_init_value(&i1); i1 < 10; ++i1) {} // no-warning
for (misra_14_2_init_value_1(&i2); i2 < 10; ++i2) {} // no-warning

bool abort = false;
for (i = 0; (i < 10) && !abort; ++i) { // 14.2 as 'i' is not a variable
Expand Down

0 comments on commit f7b7237

Please sign in to comment.