Skip to content

Fix IndexOutOfRangeException for query segments without '=' in ChorusHubServerInfo#379

Merged
imnasnainaec merged 9 commits into
masterfrom
fix/chorushub-query-parse
Jul 24, 2026
Merged

Fix IndexOutOfRangeException for query segments without '=' in ChorusHubServerInfo#379
imnasnainaec merged 9 commits into
masterfrom
fix/chorushub-query-parse

Conversation

@imnasnainaec

@imnasnainaec imnasnainaec commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Two bugs in the manual query-string parser in `ChorusHubServerInfo.GetValue`:

  1. Unreachable guard: `parts.Length < 1` was never true — `String.Split` always returns at least one element. A bare flag segment (no `=`) would throw `IndexOutOfRangeException` on `parts[1]`. Fix: change the guard to `parts.Length < 2`.

  2. Truncated values: Splitting on all `=` characters turned `key=val=ue` into a 3-element array; only `parts[1]` was used, silently dropping everything after the second `=`. Fix: use `Split(new[] { '=' }, 2)` so the full remainder becomes `parts[1]`.

`HttpUtility.ParseQueryString` was considered but rejected: it URL-decodes values while `ToString()` does not URL-encode them, creating a round-trip asymmetry. Fixing that with `Uri.EscapeDataString` would encode colons in IPv6 addresses, breaking old clients. Since all values are machine-generated and will never contain `+` or `%`, the manual parser is correct with just these two fixes.

Fixes #372

Devin review: https://app.devin.ai/review/sillsdev/chorus/pull/379


This change is Reviewable

@imnasnainaec imnasnainaec self-assigned this Jun 22, 2026
@imnasnainaec
imnasnainaec marked this pull request as ready for review June 22, 2026 18:59
@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown

Test Results

       8 files  ±0     334 suites  +1   2h 25m 10s ⏱️ - 2m 24s
   996 tests +4     940 ✔️ +4    56 💤 ±0  0 ±0 
3 161 runs  +4  3 038 ✔️ +4  123 💤 ±0  0 ±0 

Results for commit dd760c8. ± Comparison against base commit 7313dd6.

♻️ This comment has been updated with latest results.

@imnasnainaec
imnasnainaec marked this pull request as draft June 23, 2026 10:32
@imnasnainaec
imnasnainaec marked this pull request as ready for review June 23, 2026 17:41
Comment thread src/ChorusHubTests/ChorusHubTests.cs
Comment thread src/LibChorus/ChorusHub/ChorusHubServerInfo.cs Outdated
imnasnainaec added a commit that referenced this pull request Jul 2, 2026
…g them

Addresses review feedback on #379: a segment without '=' (e.g. 'flag')
is now stored with an empty-string value, distinguishable from an
absent parameter (which GetValue reports as "?").

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@imnasnainaec
imnasnainaec force-pushed the fix/chorushub-query-parse branch from 988875b to c536738 Compare July 2, 2026 13:03
imnasnainaec and others added 8 commits July 2, 2026 09:46
… query flags

String.Split always returns at least one element, so the guard `parts.Length < 1`
was unreachable. Any query segment without '=' would throw on `parts[1]`.
Change the guard to `parts.Length < 2` so those segments are skipped safely.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Splitting on all '=' would silently drop everything after the second '='
in a value like key=val=ue. Use Split(..., 2) so the key is parts[0]
and the full remainder (including any embedded '=') is parts[1].

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The hand-rolled split loop had two bugs (unreachable guard for missing '=',
truncated values containing '='). Replace it with HttpUtility.ParseQueryString,
consistent with how UrlHelper parses query strings elsewhere in the library.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
HttpUtility.ParseQueryString URL-decodes values, so ToString() must
URL-encode them to avoid silent corruption on a round-trip. Use
Uri.EscapeDataString on all string fields. Also remove the now-unused
System.Collections.Specialized import left over from the old manual parser.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
HttpUtility.ParseQueryString introduced a round-trip asymmetry (URL-decoding
on parse but no encoding on serialization), and fixing that with
Uri.EscapeDataString would encode IPv6 colons, breaking old clients. Since
all values are machine-generated and will never contain '+' or '%', the
manual parser is correct as-is with the two fixes: guard parts.Length < 2
to skip bare flags, and Split(..., 2) to preserve '=' in values.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…e fix

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…g them

Addresses review feedback on #379: a segment without '=' (e.g. 'flag')
is now stored with an empty-string value, distinguishable from an
absent parameter (which GetValue reports as "?").

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@imnasnainaec
imnasnainaec force-pushed the fix/chorushub-query-parse branch from c536738 to 91ee5ad Compare July 2, 2026 13:46

@imnasnainaec imnasnainaec left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@imnasnainaec reviewed all commit messages and resolved 1 discussion.
Reviewable status: 0 of 3 files reviewed, all discussions resolved.

@imnasnainaec
imnasnainaec requested a review from rmunn July 2, 2026 15:47

@rmunn rmunn left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@rmunn

rmunn commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

This is perfect now: fixes the bug without discarding valueless parameters, so that &flag can be used in the future.

@imnasnainaec
imnasnainaec merged commit d8413af into master Jul 24, 2026
7 of 8 checks passed
@imnasnainaec
imnasnainaec deleted the fix/chorushub-query-parse branch July 24, 2026 12:26
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.

IndexOutOfRangeException in ChorusHubServerInfo.GetValue when query segment has no '='

2 participants