charmbracelet / charmbracelet/x
bug(ansi): Truncate, TruncateLeft etc do not obey length in many cases
- Dominant language
- Go
- Stars
- 314
- Forks
- 94
- Avg merge
- 3d 22h
- Merged PRs (30d)
- 2
Description
### Describe the bug
In many cases, `Truncate`, `TruncateLeft`, and potentially other functions do not obey the provided length, at least lengths that get returned by `StringWidth`.
### To Reproduce
Use the following patch to add fuzzing for `Truncate` and `TruncateLeft`:
```patch
diff --git a/ansi/truncate_test.go b/ansi/truncate_test.go
index decf11a..17e5ba3 100644
--- a/ansi/truncate_test.go
+++ b/ansi/truncate_test.go
@@ -1,6 +1,7 @@
package ansi
import (
+ "math/rand"
"testing"
)
@@ -458,3 +459,35 @@ func TestByteToGraphemeRange(t *testing.T) {
})
}
}
+
+func FuzzTruncate(f *testing.F) {
+ for _, tc := range tcases {
+ f.Add(tc.input)
+ }
+
+ f.Fuzz(func(t *testing.T, input string) {
+ n := rand.Intn(100) + 1
+ result := Truncate(input, n, "…")
+ w := StringWidth(result)
+
+ if w > n {
+ t.Errorf("expected width to be no greater than %d, got %d", n, w)
+ }
+ })
+}
+
+func FuzzTruncateLeft(f *testing.F) {
+ for _, tc := range tcases {
+ f.Add(tc.input)
+ }
+
+ f.Fuzz(func(t *testing.T, input string) {
+ n := rand.Intn(100) + 1
+ result := TruncateLeft(input, n, "…")
+ w := StringWidth(result)
+
+ if w > n {
+ t.Errorf("expected width to be no greater than %d, got %d", n, w)
+ }
+ })
+}
```
And run with:
```console
$ go test -run=".*" -fuzz="^FuzzTruncate$" ./ansi/
# or
$ go test -run=".*" -fuzz="^FuzzTruncateLeft$" ./ansi/
```
I get failures nearly instantly. An example of 1:
```
string("\x9f \xec؋\xf00")
```
### Expected behavior
The above fuzzing methods simply check to see if the resulting output from either function is ever **longer** (according to `ansi.StringWidth()`) than the provided max length passed to the associated function. I would expect that the result to always be truncated and **never exceed the length provided as the input**, at least according to the "length" that `ansi.StringWidth()` also calculates.
Contributor guide
Research direction
Start in ansi/truncate_test.go and run the provided Go fuzz commands for FuzzTruncate and FuzzTruncateLeft to reproduce the width failures. Trace Truncate and TruncateLeft from those tests, then verify that fuzz-generated results never have StringWidth greater than the supplied length for either function.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 52/100