Skip to content

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

Open
imnasnainaec wants to merge 8 commits into
masterfrom
fix/chorushub-query-parse
Open

Fix IndexOutOfRangeException for query segments without '=' in ChorusHubServerInfo#379
imnasnainaec wants to merge 8 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 20m 54s ⏱️ - 8m 32s
   996 tests +4     940 ✔️ +4    56 💤 ±0  0 ±0 
3 161 runs  +4  3 038 ✔️ +4  123 💤 ±0  0 ±0 

Results for commit 91ee5ad. ± Comparison against base commit b115dd0.

♻️ 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
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