Skip to content

Guard joined-value completion against prefix/separator overlap#178

Merged
Taywee merged 1 commit into
Taywee:masterfrom
metsw24-max:completion-separator-prefix-overlap
Jun 2, 2026
Merged

Guard joined-value completion against prefix/separator overlap#178
Taywee merged 1 commit into
Taywee:masterfrom
metsw24-max:completion-separator-prefix-overlap

Conversation

@metsw24-max
Copy link
Copy Markdown
Contributor

Harden the bash-completion path against invalid prefix/separator combinations that can cause std::string::substr() to throw std::out_of_range.

When a custom LongSeparator() overlaps the configured long-option prefix (for example, LongSeparator("-") with the default "--" prefix), find(longseparator) may return a position inside the prefix itself. The completion handler then constructs an arg string shorter than longprefix and subsequently calls:

arg.substr(longprefix.size())

which throws std::out_of_range.

Root Cause

The joined-value completion path assumed that any discovered separator would occur at or beyond the end of the long-option prefix. That invariant was not enforced.

For overlapping prefix/separator configurations, arg may become shorter than longprefix, making:

arg.substr(longprefix.size())

invalid.

In throwing builds, the resulting std::out_of_range escapes as a non-args exception. Under ARGS_NOEXCEPT, the throwing substr() call breaks the no-throw expectation and may result in termination when exceptions are disabled.

Fix

Only attempt joined-value completion when the separator is located at or beyond the end of the long-option prefix:

if (separator != chunk.npos && separator >= longprefix.size())

This prevents invalid substr() calls while preserving existing behavior for valid completion inputs.

Tests

Added two regression tests:

  • test/completion_separator_prefix_overlap.cxx

    • Verifies that completion handling follows the normal args::Completion path instead of leaking std::out_of_range.
  • test/noexcept_completion_separator_prefix_overlap.cxx

    • Verifies correct behavior under ARGS_NOEXCEPT, ensuring completion is reported through the parser error state without throwing.

Both tests fail on the unpatched code and pass with this change.

Files Changed

  • args.hxx
  • test/completion_separator_prefix_overlap.cxx
  • test/noexcept_completion_separator_prefix_overlap.cxx

@Taywee
Copy link
Copy Markdown
Owner

Taywee commented Jun 2, 2026

Makes sense to me. Thanks for the PR.

@Taywee Taywee merged commit 66dc042 into Taywee:master Jun 2, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants