Skip to content

ext/strings: add cost estimators for string extension functions#1297

Open
mohammadmseet-hue wants to merge 1 commit intogoogle:masterfrom
mohammadmseet-hue:add-string-cost-estimators
Open

ext/strings: add cost estimators for string extension functions#1297
mohammadmseet-hue wants to merge 1 commit intogoogle:masterfrom
mohammadmseet-hue:add-string-cost-estimators

Conversation

@mohammadmseet-hue
Copy link
Copy Markdown

Summary

The ext.Strings library registers 13+ string manipulation functions without any compile-time cost estimators or runtime cost trackers. All string extension functions fall through to a default O(1) cost in both the static cost checker (checker/cost.go) and runtime cost tracker (interpreter/runtimecost.go), regardless of actual input size or computational complexity.

Every other CEL-GO extension library registers cost estimators: ext/lists.go has 28, ext/regex.go has 15, ext/sets.go has 12. ext/strings.go has zero.

This means cel.CostLimit() is ineffective for expressions using string extension functions. For example, chaining split("") and join("XXX") calls can amplify a small input into significant memory allocation while the cost tracker reports a trivially low cost.

Changes

  • Added checker.OverloadCostEstimate entries in CompileOptions() for all string extension overloads
  • Added interpreter.OverloadCostTracker entries in ProgramOptions() for all string extension overloads
  • Cost estimation follows the same patterns used by ext/regex.go and ext/lists.go:
    • O(n) traversal cost for simple operations (charAt, lowerAscii, upperAscii, trim, reverse, substring)
    • O(n*m) search cost for indexOf/lastIndexOf
    • Proportional cost with output size tracking for replace, split, and join
  • strings.quote and string.format are excluded as they are already tracked by the default runtime cost calculator via overloads.ExtQuoteString and overloads.ExtFormatString

Affected overloads

Overload ID Previous Cost New Cost
string_char_at_int O(1) O(n)
string_index_of_string O(1) O(n*m)
string_index_of_string_int O(1) O(n*m)
string_last_index_of_string O(1) O(n*m)
string_last_index_of_string_int O(1) O(n*m)
string_lower_ascii O(1) O(n)
string_upper_ascii O(1) O(n)
string_replace_string_string O(1) O(n) + result size
string_replace_string_string_int O(1) O(n) + result size
string_split_string O(1) O(n) + list allocation
string_split_string_int O(1) O(n) + list allocation
string_substring_int O(1) O(n)
string_substring_int_int O(1) O(n)
string_trim O(1) O(n)
string_reverse O(1) O(n)
list_join O(1) O(n) + result size
list_join_string O(1) O(n) + result size

Test plan

  • All existing tests pass (go test ./ext/... and go test ./...)
  • No changes to test expectations required — the strings.quote tests are unaffected since quote/format are handled by the default runtime cost calculator

The ext.Strings library registers 13+ string manipulation functions
(split, join, replace, indexOf, etc.) without any compile-time cost
estimators or runtime cost trackers. All string extension functions
fall through to a default O(1) cost, regardless of actual input size.

This means CEL cost limits are ineffective for string extension
operations: a split("").join("XXX") chain can amplify a 10KB input
into 63MB of memory allocation while the cost tracker reports a
total cost of 9.

Add CostEstimatorOptions to CompileOptions() and CostTrackerOptions
to ProgramOptions() for all string extension overloads, following
the same pattern used by ext/regex.go and ext/lists.go.

The strings.quote and string.format overloads are excluded as they
are already tracked by the default runtime cost calculator via
overloads.ExtQuoteString and overloads.ExtFormatString.

Fixes cost tracking for: charAt, indexOf, lastIndexOf, lowerAscii,
upperAscii, replace, split, join, substring, trim, and reverse.
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.

1 participant