Menu

for() loop seems to hide some issues

2019-03-05
2019-03-09
  • Neil Matthews

    Neil Matthews - 2019-03-05

    cppcheck --version
    Cppcheck 1.87

    for() loop seems to hide uninitialized variable

    cppcheck --enable=all -DLOOP=0 for_loop_hides_uninit.c
    and
    cppcheck --enable=all -DLOOP=0 for_loop_hides_uninit.c
    both report an uninitialised variable.

    But
    cppcheck --enable=all -DLOOP=2 for_loop_hides_uninit.c
    doesn't report the uninitialised variable.

    Note: original code had a variable rather than a #define and behaved as -DLOOP=2

     
  • Neil Matthews

    Neil Matthews - 2019-03-05

    Bother second -DLOOP=0 should be -DLOOP=1

     
  • versat

    versat - 2019-03-06

    With Cppcheck 1.87 i can reproduce this.
    With the latest git head Cppcheck does not report any uninitialized variable for this example, not even inconclusive.
    Maybe Cppcheck avoids to report a false positive here because it can not now the value of argc. But otherwise the else branch would be redundant if argc is always greater than 1.
    IMHO Cppcheck should warn in this case because there is clearly at least one path where the variable can be uninitialized.
    The latest Cppcheck does not warn for this reduced example that does not use a macro but uses 1 instead of the LOOP macro:

    #include <stdio.h>
    #include <string.h>
    
    int main(int argc, char *argv[])
    {
       int i;
       char value;
    
       for(i = 0; i < 1; i++)
       {
           if(argc > 1)
           {
               value = 0;
           }
        }
    
        printf("global %c\n", value);
    
        return 0;
    }
    

    Output

    $ ./cppcheck --enable=all --inconclusive for_loop_hides_uninit.c
    Checking for_loop_hides_uninit.c ...
    (information) Cppcheck cannot find all the include files (use --check-config for details)
    

    And even when disabling the for loop Cppcheck does not warn. In this case the variable is always uninitialized:

    #include <stdio.h>
    #include <string.h>
    
    int main(int argc, char *argv[])
    {
       int i;
       char value;
    
       for(i = 0; i < 0; i++)
       {
           if(argc > 1)
           {
               value = 0;
           }
        }
    
        printf("global %c\n", value);
    
        return 0;
    }
    
    $ ./cppcheck --enable=all --inconclusive for_loop_hides_uninit.c
    Checking for_loop_hides_uninit.c ...
    (information) Cppcheck cannot find all the include files (use --check-config for details)
    

    Looks like a regression. What would you say Daniel?

     
  • versat

    versat - 2019-03-06

    Maybe a slightly related ticket:
    https://trac.cppcheck.net/ticket/8276

     
  • Daniel Marjamäki

    yes we should warn in both cases. Thanks.. I will try to look at this asap.. or create a ticket.

     
  • Daniel Marjamäki

    I created this ticket: https://trac.cppcheck.net/ticket/9030

    We should add proper ValueFlow analysis for this.

    I am very grateful that this false negative was reported.

     
  • Daniel Marjamäki

    To clarify... we need to check that argc is unchanged in the loop. Imagine:

       for(i = 0; i < 10; i++)
       {
           if(argc > 1)
           {
               value = 0;
           }
           argc = dostuff();
        }
    

    Here it is not conclusive if it would be possible with uninitialized value after the loop...

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.