Skip to content

Commit

Permalink
color: Fix an assertion failure with embedded NUL bytes
Browse files Browse the repository at this point in the history
Leading NUL bytes (e.g. `*\0.gz=...`) could cause us to insert a
non-prefix-free set of strings into the case-insensitive extension trie,
which would lead to crashes like

   bfs: trie_split@src/trie.c:538: Assertion failed: `key_nibble != rep_nibble`

and OOB accesses to trie leaf keys.  Fix it by ignoring those
extensions, since filenames cannot contain NUL bytes.

Fixes: 08030ae ("color: Delay the case_sensitive decision")
  • Loading branch information
tavianator committed Oct 2, 2024
1 parent 9c9dc01 commit f5eaadb
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/color.c
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,16 @@ static int insert_ext(struct trie *trie, struct ext_color *ext) {
/** Set the color for an extension. */
static int set_ext(struct colors *colors, dchar *key, dchar *value) {
size_t len = dstrlen(key);

// Embedded NUL bytes in extensions can lead to a non-prefix-free
// set of strings, e.g. {".gz", "\0.gz"} would be transformed to
// {"zg.\0", "zg.\0\0"} (showing the implicit terminating NUL).
// Our trie implementation only supports prefix-free key sets, but
// luckily '\0' cannot appear in filenames so we can ignore them.
if (memchr(key, '\0', len)) {
return 0;
}

struct ext_color *ext = varena_alloc(&colors->ext_arena, len + 1);
if (!ext) {
return -1;
Expand Down
27 changes: 27 additions & 0 deletions tests/bfs/color_ext_case_nul.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
$'rainbow/\e[1m'
$'rainbow/\e[1m/'$'\e[0m'
rainbow
rainbow/lower.gz
rainbow/lower.tar.gz
rainbow/lu.tar.GZ
rainbow/ul.TAR.gz
rainbow/upper.GZ
rainbow/upper.TAR.GZ
rainbow/exec.sh
rainbow/socket
rainbow/broken
rainbow/chardev_link
rainbow/link.txt
rainbow/sticky_ow
rainbow/sgid
rainbow/pipe
rainbow/ow
rainbow/sugid
rainbow/suid
rainbow/sticky
rainbow/file.dat
rainbow/file.txt
rainbow/lower.tar
rainbow/mh1
rainbow/mh2
rainbow/upper.TAR
5 changes: 5 additions & 0 deletions tests/bfs/color_ext_case_nul.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Regression test: embedded NUL bytes in an extension caused an assertion
# failure in the trie implementation

export LS_COLORS='*.gz=01;31:*\0.GZ=01;32:'
bfs_diff rainbow -color

0 comments on commit f5eaadb

Please sign in to comment.