V: enable stack usage guard#4387
Conversation
4ea70eb to
e1546c1
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #4387 +/- ##
==========================================
- Coverage 85.98% 85.97% -0.02%
==========================================
Files 255 256 +1
Lines 63884 64023 +139
==========================================
+ Hits 54931 55042 +111
- Misses 8953 8981 +28 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Enables an opt-in stack usage guard to mitigate stack overflows during parsing (notably for the V parser), and adds a CLI option to configure the guard’s limit.
Changes:
- Add stack guard infrastructure (
main/stackguard.c,main/stackguard_p.h) and wire it into the parse loop via per-parserdiscardInput. - Enable the guard in the V parser and expose
--stack-limit=<bytes>plus diagnostics (verbose + totals). - Update build files (make + VS project) and adjust expected outputs for updated diagnostics.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| win32/ctags_vs2013.vcxproj.filters | Adds stackguard sources/headers to VS filters for building on Windows. |
| win32/ctags_vs2013.vcxproj | Includes stackguard source/header in the VS project build. |
| source.mak | Adds stackguard source/header to the build lists for non-Windows builds. |
| parsers/v.c | Enables stack guard checks in an expression list parse path; provides parser-specific EOF discard function. |
| main/stats.c | Prints observed peak stack usage in totals output. |
| main/stackguard_p.h | Declares the stack guard API used by main/options/parse/stats. |
| main/stackguard.c | Implements stack tracking, limit handling, and peak usage tracking. |
| main/parse_p.h | Declares the query function for stack-guard support (typo present). |
| main/parse.h | Adds discardInputFn hook and exposes stackGuardCheck to parsers. |
| main/parse.c | Prepares/releases stack guard around parser execution; adds support query function (typo present). |
| main/options.c | Adds --stack-limit option and prints “stack guard supported/unsupported” in language description; updates some error messages. |
| main/main.c | Logs the computed stack limit in verbose mode. |
| configure.ac | Detects sys/resource.h for getrlimit-based default limit computation. |
| Tmain/versioning.d/stdout-expected.txt | Updates expected “describe language” output for “stack guard” line. |
| Tmain/broken-tagname.d/stderr-expected.txt | Updates expected verbose output to include stack limit line. |
| Tmain/broken-tagname.d/run.sh | Adds --stack-limit=8192 to stabilize verbose output and adjusts sed formatting. |
| Tmain/broken-tagname-in-ectags-format.d/stderr-expected.txt | Updates expected verbose output to include stack limit line. |
| Tmain/broken-tagname-in-ectags-format.d/run.sh | Adds --stack-limit=8192 to stabilize verbose output. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (!stackGuardCheck(token)) | ||
| return; |
There was a problem hiding this comment.
This introduces new control-flow behavior (early return + EOF discard) when the stack limit is exceeded, but the PR description lists 'add test cases' as TODO and the current diffs only stabilize verbose output tests. Add an integration test that forces deep nesting in V input (or a dedicated selftest parser case) to assert: (1) a NOTICE is emitted about exceeding the limit, and (2) parsing terminates safely without crashing/hanging.
f70ab53 to
7cd2d3a
Compare
08e746e to
dc4393b
Compare
dc4393b to
cc96186
Compare
a038815 to
5df0ca9
Compare
Signed-off-by: Masatake YAMATO <[email protected]>
Signed-off-by: Masatake YAMATO <[email protected]>
Signed-off-by: Masatake YAMATO <[email protected]>
Signed-off-by: Masatake YAMATO <[email protected]>
…help message at runtime Signed-off-by: Masatake YAMATO <[email protected]>
56ee44b to
2043dca
Compare
|
The DTS parser looks broken. |
|
ulimit based test may not work on Windows. |
Introduce a stack usage guard to prevent stack overflow
in deeply nested input.
The default stack limit is derived from the value
returned by getrlimit(RLIMIT_STACK). On platforms where
getrlimit() is not available, a default limit of about
1MB is used, with a 32kB safety margin reserved.
The limit can be adjusted with the --stack-limit=<bytes>
option.
The --verbose option prints the stack limit actually used:
$ ./ctags --help
...
--stack-limit=<bytes>
Limit the stack usage while parsing, in bytes [8372224].
$ ./ctags --stack-limit=81920 --help
...
--stack-limit=<bytes>
Limit the stack usage while parsing, in bytes [81920].
...
The --totals option prints the observed peak stack usage:
$ ./ctags --totals -o - main/main.c > /dev/null
1 file, 612 lines (13 kB) scanned in 0.0 seconds (4710 kB/s)
20 tags added to tag file
20 tags sorted in 0.00 seconds
Observed peak stack usage: 4096 bytes (4.0 KiB)
This change introduces the infrastructure in the main
part. Individual parsers must explicitly enable the guard
to benefit from stack protection.
Signed-off-by: Masatake YAMATO <[email protected]>
Signed-off-by: Masatake YAMATO <[email protected]>
Signed-off-by: Masatake YAMATO <[email protected]>
Signed-off-by: Masatake YAMATO <[email protected]>
4bf2fdd to
6fa47df
Compare
… user mode Signed-off-by: Masatake YAMATO <[email protected]>
Partially fixes: universal-ctags#4369 Partially addresses: CVE-2026-2641 Signed-off-by: Masatake YAMATO <[email protected]>
The stack guard limits the recursion in parsing. I found the stack guard is not enough to use ctags with bad input. If parser->requestAutomaticFQTag is enabled, ctags fills scope field of tags automatically based on cork indexes signed to scopeIndex member of tagEntryInfo. If the scope is too deep, filling takes too long time. This change limits the depth of scope to 32. Unlike the stack guard, I hard-coded to limit. Signed-off-by: Masatake YAMATO <[email protected]>
Fixes: universal-ctags#4409 Signed-off-by: Masatake YAMATO <[email protected]>
|
Cygwin: FreeBSD: ctags on both platforms use getrlimit. |
| { | ||
| rlim_t cur = rlim.rlim_cur; | ||
|
|
||
| if (rlim.rlim_cur == RLIM_INFINITY || cur > (rlim_t) SIZE_MAX) |
There was a problem hiding this comment.
The way to handle RLIM_INFINITY is completely wrong.
If a user specifies RLIM_INFINITY (via ulimit -s), ctags should disable the stack usage guard.
Fixes #4369 (CVE-2026-2641)
Fixes #4409
GHSA-69fg-c96p-c6fq
Author: Masatake YAMATO [email protected]
Date: Fri Feb 20 04:23:04 2026 +0900
Author: Masatake YAMATO [email protected]
Date: Fri Feb 20 04:22:45 2026 +0900
TODO: