Segfault if base language flags given while new subparser uses `{dedicated}` mode
ctags segfaults given the following options.ctags and a .cpp file to parse:
--kinds-C++=*
--langdef=Test{base=C++}{dedicated}
--map-C++=-.cpp
--map-Test=+.cpp
--_tabledef-Test=main
--_mtable-regex-Test=main/.//
If the --kinds-C++=* is removed, it works fine. If it's replaced with --fields-C++=+{properties} it segfaults. So long as no C++-specific options are given, it works fine.
Alternatively, if --langdef=Test{base=C++}{dedicated} is changed to --langdef=Test{base=C++}, it does not segfault. (of course it doesn't invoke the C++ parser either, but that's expected in that case)
The crash seems to occur due to getNextSubparser() in parse.c invoking t = getSubparserLanguage(r);, and then getSubparserLanguage() in dependency.c just doing return s->slaveParser->id;. Dereferencing the s->slaveParser is invalid, as it's NULL in this case.
I added an Assert(s->slaveParser); in getSubparserLanguage() and it asserted:
ctags: main/dependency.c:194: getSubparserLanguage: Assertion `s->slaveParser' failed.
I don't know this code well enough to know what should happen, so can't fix it myself.
$ ./ctags --version
Universal Ctags 0.0.0(9ffe430a), Copyright (C) 2015 Universal Ctags Team
Universal Ctags is derived from Exuberant Ctags.
Exuberant Ctags 5.8, Copyright (C) 1996-2009 Darren Hiebert
Compiled: Aug 12 2018, 11:15:35
URL: https://ctags.io/
Optional compiled features: +wildcards, +regex, +iconv, +debug, +option-directory, +case-insensitive-filenames
I knew it. I am surprised at this report because I expect none can find this bug.
This is related to the order of the initializations of parsers.
Original I expected initializations are done in following steps.
- Links between parsers including relations base parsers and subparsers are established. (linking stage)
- initialize parsers
In your case, My code expects --langdef=Test{base=C++}{dedicated} is evaluated before initializing C++ parser. However, --kinds-C++=* triggers initializing C++ parser. This breaks my (wrong) expectation.
This doesn't happen if the Test parser is converted to C code by optlib2c because we can expect
the linking stage is done before evaluating --kinds-C++=*.
Normal users may not know the langdef flags because the option for listing them is done by --_list-langdef-flags option. Options started from _ is never listed in --help option. Furthermore, I will not write the option to our man page. So only a heavy user like you may encounter the bug. As you guess, you are the first person.
I have to rewrite the parser initialization code to fix this. However, I will not work on this item till releasing 6.0.
As you guess, you are the first person.
Cool, do I get some award? 😄
However, I will not work on this item till releasing 6.0.
ok sounds good. Thanks!
BTW, I've confirmed if I move the --kinds-C++=* to be after the --langdef=Test{base=C++}{dedicated}, it works fine.
I'll send an award.
A bug in the same area is spotted during reviewing a pull request, https://github.com/universal-ctags/ctags/pull/2926 .