Menu

Crash when parsing angle brackets in template with type traits (assertion failure)

2019-11-26
2019-11-28
  • Wesley King

    Wesley King - 2019-11-26

    In the following scenario cppcheck will fail to fix the angle brackets, causing an assertion failure later on in TemplateSimplifier#getTemplateNamePosition:

    template <typename S, enable_if_t<(is_compile_string<S>::value), int>> void i(S s);
    

    Output from cppheck:

    cppcheck: ../lib/templatesimplifier.cpp:1437: int TemplateSimplifier::getTemplateNamePosition(const Token*): Assertion `tok && tok->str() == ">"' failed.
    [1]    162439 abort (core dumped)  cppcheck --verbose --enable=all --inconclusive 
    

    Here is a test case for TestSimplifyTemplate:

    void template154() {
         const char code[] = "template <typename S, enable_if_t<(is_compile_string<S>::value), int>> void i(S s);";
         const char exp[] = "template < typename S , enable_if_t < ( is_compile_string < S > :: value ) , int > > void i ( S s ) ;";
       ASSERT_EQUALS(exp, tok(code));
       }
    

    The issue can be fixed with the following workaround (although I doubt this is the correct solution):

    --- c/lib/templatesimplifier.cpp
    +++ w/lib/templatesimplifier.cpp
    @@ -514,7 +514,7 @@ unsigned int TemplateSimplifier::templateParameters(const Token *tok)
                 return 0;
    
             // num/type ..
    -        if (!tok->isNumber() && tok->tokType() != Token::eChar && !tok->isName() && !tok->isOp())
    +        if (!tok->isNumber() && tok->tokType() != Token::eChar && !tok->isName() && !tok->isOp() && level == 0)
                 return 0;
             tok = tok->next();
             if (!tok)
    
     
  • versat

    versat - 2019-11-28

    Thanks for the detailed report.
    I have created a ticket in Trac.
    I am not familiar with such code, how do you compile it? What headers are needed to get this compiled (with -fsyntax-only)? I guess <type_traits>, but that is obviously not enough.

     

    Last edit: versat 2019-11-28
  • Wesley King

    Wesley King - 2019-11-28

    I stumbled on this issue in a file included from spdlog (https://github.com/gabime/spdlog/blob/v1.x/include/spdlog/fmt/bundled/format.h)
    line 2567.

    It looks like the key to reproducing this is using these struct defs:

    struct compile_string {};
    
    template <typename S>
    struct is_compile_string : std::is_base_of<compile_string, S> {};
    

    You should be able to reproduce the problem in that code base with

    cppcheck -I include --enable=all --inconclusive src/spdlog.cpp

     

    Last edit: Wesley King 2019-11-28

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.