Skip to content

Accept end == size() in two-argument string substring - #2443

Merged
copybara-service[bot] merged 1 commit into
cel-expr:masterfrom
timoklock:fix-substring-end-at-size
Nov 11, 2026
Merged

copybara-service[bot] merged 1 commit into
cel-expr:masterfrom
timoklock:fix-substring-end-at-size

Conversation

@timoklock

Copy link
Copy Markdown
Contributor

Fixes #2442.

<string>.substring(start, end) returned <start> or <end> is greater than <string>.size() whenever end equalled the string's length and start < end, so 'abc'.substring(1, 3) failed instead of returning 'bc'. The strings extension defines the end offset as exclusive and only out-of-range or inverted bounds as errors, which is what cel-go implements.

Both SubstringImpl(…, start, end) overloads (string_view and Cord) return from inside the loop only when they reach end with input left. After the loop they handled only start == end == size. The post-loop check now records start and returns when end sits at the end of the input, the same two steps the loop body takes.

Tests:

  • StringValueTest.Substring: Substring(4, 6), (0, 6) and (6, 6) on the six-code-point €€€€€€, for both the cord-backed and the view-backed value.
  • StringsExtFunctionsTest (parse, check and evaluate): 'tacocat'.substring(4, 7) == 'cat', 'tacocat'.substring(0, 7) == 'tacocat', 'ta©o©αT'.substring(4, 7) == '©αT'.

Reference to test cases in cel-go

https://github.com/cel-expr/cel-go/blob/b6d796fb74036b0251ee055f824917cbf4ce6f18/ext/strings_test.go#L88-L93

`<string>.substring(start, end)` failed with "<start> or <end> is
greater than <string>.size()" whenever `end` equalled the string's
length and `start < end`, so `'abc'.substring(1, 3)` errored instead of
returning `'bc'`. The end offset is exclusive, so `end == size()` is the
only way to take a range that includes the last character.

Both `SubstringImpl(..., start, end)` overloads returned from inside the
loop only when they reached `end` with input left, and after the loop
handled only `start == end == size`. The post-loop check now records
`start` and returns when `end` sits at the end of the input.
@jnthntatum

Copy link
Copy Markdown
Collaborator

/gcbrun

@jnthntatum

Copy link
Copy Markdown
Collaborator

Thanks for the fix! LGTM -- this will get merged by the bot after internal approvals.

@copybara-service
copybara-service Bot merged commit 91a6986 into cel-expr:master Nov 11, 2026
8 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.

<string>.substring(start, end) errors when end == size() and start < end

2 participants