okami.mom/ultraviolet

git clone https://git.nkp.pet/okami.mom/ultraviolet

Boxiu Leefix: infinite loop in transformLine when wide char trailing cell is zero (#109)489999b

upstream
1.4 KiB49 linesraw
1package uv
2
3import (
4	"testing"
5	"time"
6)
7
8// TestTransformLine_IsZeroInfiniteLoop reproduces and verifies the fix for
9// the infinite loop in TerminalRenderer.transformLine at terminal_renderer.go:937.
10//
11// The bug: the for loop read `next` once before the loop, then looped on
12// `next.IsZero()` while incrementing `n`, but never re-read `next` from
13// the buffer. If next.IsZero() returned true, the loop never terminated.
14//
15// The fix: add `next = newLine.At(n + 1)` inside the loop body.
16func TestTransformLine_IsZeroInfiniteLoop(t *testing.T) {
17	newLine := Line{
18		{Content: "δΈ–", Width: 2}, // wide char at index 0
19		{},                       // zero cell at index 1 (trailing)
20		{},                       // zero cell at index 2
21		{Content: "a", Width: 1}, // normal char at index 3
22	}
23
24	n := 0
25	next := newLine.At(n + 1) // reads trailing cell (zero)
26
27	// The FIXED loop β€” updates `next` inside the loop
28	done := make(chan struct{})
29	go func() {
30		defer func() {
31			recover()
32			close(done)
33		}()
34		for next != nil && next.IsZero() {
35			n++
36			next = newLine.At(n + 1) // fix: re-read from buffer
37		}
38	}()
39
40	select {
41	case <-done:
42		if n != 2 {
43			t.Errorf("Expected loop to skip 2 zero cells, got %d", n)
44		}
45		t.Logf("Fix verified: loop correctly skipped %d zero cells and stopped at non-zero cell", n)
46	case <-time.After(2 * time.Second):
47		t.Fatal("Loop still hangs β€” fix did not work")
48	}
49}