Commit dd2a141
committed
fix: eliminate panics, restore Sprig math parity, fix mixed numeric comparisons
Bump version to 0.7.6.
Panic fixes (user-triggerable, no longer reachable):
- utils::unqote: guard the 2-byte slice against non-char-boundary and short
inputs. A string literal containing a backslash followed by a multibyte
character (e.g. `\…`) panicked with `byte index 2 is not a char boundary`.
- helm_functions::logic::value_is_truthy: `n.as_f64().unwrap() == 0.0`
panicked on any integer `Number`, because `gtmpl_value::Number::as_f64`
only returns `Some` for the float variant. Cascade through as_f64 ->
as_i64 -> as_u64. This path is used by `default`, `empty`, `coalesce`,
and `ternary`, so any integer flowing into those crashed the executor.
- helm_functions::string::substr: validate start/end against len and char
boundaries before slicing. Previously panicked on out-of-bounds, inverted
ranges, or non-char-boundary indices.
- helm_functions::string::trunc: fix the dead-code `negative` branch (was
parsed as usize so it was never reached), parse as i64 to accept negative
indices like Sprig, clamp over-large indices to the full string, and
validate char boundaries.
- helm_functions::string::abbrev: `max_length - 3` underflowed usize and
slicing past the end panicked. Return the input unchanged when it fits,
require at least 4 for a meaningful abbreviation, and validate the cut
against char boundaries.
- helm_functions::string::abbrevboth: same underflow + out-of-bounds
pattern; apply Sprig's "too short to abbreviate" semantics.
- helm_functions::conversion: `serde_yaml::Value::Tagged` was hitting
`unreachable!()`. Recurse into the inner value, discarding the tag.
- mows_functions::crypto::random_string: `parse::<u16>().unwrap()` on the
length argument and `rng.random_range(0..0)` on an empty charset both
panicked. Return clean errors instead.
Core numeric comparison fix (no feature flag required):
- funcs::cmp: mixed int/float comparisons like `{{ lt 5 3.5 }}` returned
`unable to compare 5 and 3.5` because the function short-circuited on
`as_f64()` which only succeeds for the float variant. Now tries exact
i64, then exact u64, then falls back to coercing both sides to f64 via
a shared `number_to_f64` helper that cascades through all variants.
Affects `lt`, `le`, `gt`, `ge`.
Helm/Sprig math parity (helm-functions feature):
- Rewrite helm_functions::math to match Sprig semantics exactly.
Integer functions (add, sub, mul, div, mod, pow, add1, max, min) now
operate on i64 and return `Value::Number` (previously returned
`Value::String`, which broke numeric pipelines). Float functions
(addf, subf, mulf, divf, add1f, maxf, minf, floor, ceil, round)
operate on f64 and return `Value::Number`. `add` and `mul` are
variadic to match Sprig. Division and modulo by zero return a clean
error instead of panicking (divergence from Go/Sprig, required to
preserve the no-panic invariant). Wrapping arithmetic matches Go's
int64 behaviour.
- Shared `to_i64` / `to_f64` helpers implement Sprig's toInt64/toFloat64
coercion (numbers, strings, bools, nil).
- helm_functions::conversion: preserve the narrowest numeric variant
(i64 -> u64 -> f64) when converting from serde_json / serde_yaml, so
integers from JSON/YAML stay integers through the math pipeline.
Tests:
- tests/panic_regressions.rs: 8 tests covering the original user report
(URL literal with %5B/%5D), integer/unsigned/zero variants in default,
and mixed int/float cmp.
- tests/panic_audit.rs: 26 tests exhaustively exercising substr/trunc/
abbrev/abbrevboth edge cases, tagged YAML values, and the math parity
across literal/context/JSON/YAML sources with div/mod-by-zero handling.
- helm_functions::math unit tests extended to cover variadic add/mul,
string inputs, div-by-zero, and fractional-result preservation.
All 269 tests pass under no-features, helm-functions, helm+mows, and
--all-features.1 parent 1444af7 commit dd2a141
10 files changed
Lines changed: 954 additions & 317 deletions
File tree
- src
- helm_functions
- mows_functions
- tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
| 3 | + | |
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
527 | 527 | | |
528 | 528 | | |
529 | 529 | | |
530 | | - | |
531 | | - | |
532 | | - | |
| 530 | + | |
533 | 531 | | |
534 | 532 | | |
535 | 533 | | |
| 534 | + | |
536 | 535 | | |
537 | 536 | | |
538 | 537 | | |
539 | | - | |
| 538 | + | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
540 | 549 | | |
541 | 550 | | |
542 | 551 | | |
| |||
545 | 554 | | |
546 | 555 | | |
547 | 556 | | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
548 | 565 | | |
549 | 566 | | |
550 | 567 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
106 | 106 | | |
107 | 107 | | |
108 | 108 | | |
109 | | - | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
110 | 124 | | |
111 | 125 | | |
112 | 126 | | |
| |||
133 | 147 | | |
134 | 148 | | |
135 | 149 | | |
136 | | - | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
137 | 163 | | |
138 | 164 | | |
139 | 165 | | |
| |||
148 | 174 | | |
149 | 175 | | |
150 | 176 | | |
151 | | - | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
152 | 181 | | |
153 | 182 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
73 | 73 | | |
74 | 74 | | |
75 | 75 | | |
76 | | - | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
77 | 85 | | |
78 | 86 | | |
79 | 87 | | |
| |||
0 commit comments