Menu

Bug in resolving #include directives

2020-06-08
2020-06-14
  • Nathan Baker

    Nathan Baker - 2020-06-08

    Consider the following bug repro:

    nathan@nathanb-dev ~/tmp/cppcheck_bug % ls
    foo.cpp
    nathan@nathanb-dev ~/tmp/cppcheck_bug % cat foo.cpp
    #include <iostream>
    
    int main(int argc, char** argv)
    {
        std::cout << "All is well" << std::endl;
        return 0;
    }
    nathan@nathanb-dev ~/tmp/cppcheck_bug % cppcheck foo.cpp
    Checking foo.cpp ...
    nathan@nathanb-dev ~/tmp/cppcheck_bug % g++ -o iostream foo.cpp
    nathan@nathanb-dev ~/tmp/cppcheck_bug % ./iostream
    All is well
    nathan@nathanb-dev ~/tmp/cppcheck_bug % cppcheck foo.cpp       
    Checking foo.cpp ...
    iostream:1:0: error: The code contains unhandled character(s) (character code=232). Neither unicode nor extended ascii is supported. [preprocessorErrorDirective]
    ELF>p@;@8
              @@@@h�������   pp-==���-=����DDPtd   DDQtdRtd-==``/lib64/ld-linux-x86-64.so.2GNU�����I��pnpGNU
    
                                                                                                                        
                                                                                                                         CB"U5��� Q ; � `@libstdc++.so.6__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6__ZNSt8ios_base4InitD1Ev_ZNSolsEPFRSoS_E_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc_ZNSt8ios_base4InitC1Ev_ZSt4coutlibm.so.6libgcc_s.so.1libc.so.6__cxa_atexit__cxa_finalize__libc_start_mainGLIBCXX_3.4GLIBC_2.2.5 t)c+u�i o�`���@@@�?�?�?��? �?
    ^
    nathan@nathanb-dev ~/tmp/cppcheck_bug % ls
    foo.cpp  iostream
    

    Note that cppcheck looks in the current directory to resolve includes, while the compiler first looks in the configured include path (/usr/include/c++ or whatever).

     
  • Daniel Marjamäki

    We do not want to include standard headers. Cppcheck uses cfg files instead those have extended information about types and functions and stuff. In theory, annotations could be added in the standard headers instead and then we would not need cfg files, but in practice that will not happen. Also, I have the feeling that there are really complex macros and templates in some system includes and we might not handle all those very well.

    The cfg file "std.cfg" is loaded automatically and that will contain information about all standard types and functions.

    If you really want to include the standard headers you can do that. You can use -I if you want to try that. But beware this can potentially cause false negatives. If a function declaration is found in a TU then the "annotations" in the std.cfg file is not used because Cppcheck assumes you have defined your own function/type.

    Feel free to try out the clang parser import. cppcheck --clang foo.cpp.

     
  • Daniel Marjamäki

    Also.. I believe that including all system headers means that execution time will "explode".

    Personally I never include standard headers iostream etc in Cppcheck analysis using -I. And I feel satisfied that Cppcheck will find enough bugs. I can not say "all bugs" .. even if you include all headers.

     
  • Nathan Baker

    Nathan Baker - 2020-06-09

    I'm not sure I understand your response.

    You don't have to include system headers if you don't want to. Just don't grab random files from the current directory instead.

     
  • Daniel Marjamäki

    ok I misunderstood.. so you have headers or whatever in some local paths that you do not want to be included.

     
  • Nathan Baker

    Nathan Baker - 2020-06-10

    Let me try to explain again.

    Assume I have a binary file in my source directory named iostream.

    If I create a .cpp file that #includes <iostream>, the compiler will correctly resolve this #include to the system headers installed with the compiler.</iostream>

    However, cppcheck will WRONGLY resolve the #include to the binary file in the current directory. This is why in my example above, cppcheck emits binary garbage -- because it is trying to read the binary file named iostream instead of the header file named iostream.

    I don't care whether cppcheck resolves the header or just ignores it. That is completely irrelevant. But pulling in a random file from the current directory is demonstrably the wrong behavior.

     
  • Daniel Marjamäki

    yes

     
  • Daniel Marjamäki

    I am not sure what the best fix is here. I haven't heard of this problem before so I have the feeling it's pretty rare. I don't think a "fully automatic" solution is wanted.. if you can solve your situation in a reasonable way that is fine.

    In theory you can fix this locally. maybe it's ok to remove/rename the binary file. maybe the source files to analyse could be copied to a different location. I wonder does this sound reasonable to you?

    Maybe you can add a empty iostream file somewhere then you should be able to include that. I don't remember off the top of my head what the search order for system includes is in our preprocessing.

     

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.