Objects fetched from the store are untrusted; several decode paths let one expand or print without limit. - blobgen.LimitReader errors past a byte cap (not io.LimitReader silent EOF). DecodeManifest reads through caps on both compressed input and decompressed output, far above any real manifest, so json.Decode cannot buffer a compressible bomb. FetchAndDecryptBlob bounds decompression to the blob recorded uncompressed_size (not the restoring host blob_size_limit). - downloadSnapshotDB streams straight from storage to its temp file with io.Copy, replacing two ReadAll calls that held the whole database twice. - FetchBlob drops the per-blob Stat round-trip, its expectedSize parameter and returned size, all of which only fed a debug log. - TTYHandler and ui.Writer escape control characters in messages, attribute keys/values, and rendered identifiers/paths before colour codes are applied, so a crafted value cannot drive the terminal. Model: opus-4-8
33 lines
890 B
Go
33 lines
890 B
Go
package ui_test
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// TestValueFormattersEscapeControlCharacters checks that a path carrying an
|
|
// ESC and a newline — the shape a symlink target read back from the
|
|
// snapshot database could take — is escaped before it reaches the output.
|
|
// Colour is off here, so the only way a control byte could appear is from
|
|
// the value itself.
|
|
func TestValueFormattersEscapeControlCharacters(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
w, buf := newTestWriter(false)
|
|
w.Infof("restoring %s", w.Path("a\x1b[31mZAP\nb"))
|
|
|
|
out := buf.String()
|
|
|
|
if strings.ContainsRune(out, '\x1b') {
|
|
t.Fatalf("raw ESC from a value survived in output: %q", out)
|
|
}
|
|
|
|
if strings.Count(out, "\n") != 1 {
|
|
t.Fatalf("a newline in a value must be escaped, not emitted raw: %q", out)
|
|
}
|
|
|
|
if !strings.Contains(out, `\x1b`) {
|
|
t.Fatalf("expected the escaped form of ESC in output: %q", out)
|
|
}
|
|
}
|