ctags icon indicating copy to clipboard operation
ctags copied to clipboard

Segfault if base language flags given while new subparser uses `{dedicated}` mode

Open hadrielk opened this issue 7 years ago • 5 comments

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

hadrielk avatar Aug 12 '18 15:08 hadrielk

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.

  1. Links between parsers including relations base parsers and subparsers are established. (linking stage)
  2. 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.

masatake avatar Aug 12 '18 18:08 masatake

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!

hadrielk avatar Aug 13 '18 02:08 hadrielk

BTW, I've confirmed if I move the --kinds-C++=* to be after the --langdef=Test{base=C++}{dedicated}, it works fine.

hadrielk avatar Aug 13 '18 03:08 hadrielk

I'll send an award.

masatake avatar Aug 14 '18 06:08 masatake

A bug in the same area is spotted during reviewing a pull request, https://github.com/universal-ctags/ctags/pull/2926 .

masatake avatar Apr 25 '21 07:04 masatake