Pádraig Brady <[email protected]> writes:

> From: Ismail Ramzi <[email protected]>
>
> parse_ls_color stores color_indicator[C_LINK].string as a pointer into
> the color_buf buffer, then frees color_buf on the unparsable-value path.
> The "ln=target" check after the parse loop still read that freed buffer,
> e.g. with LS_COLORS='ln=target:x'.  Skip it on the failure path, where
> color output is disabled anyway and the buffer is gone.
> * src/ls.c (parse_ls_color): Return after freeing color_buf on failure,
> so the color_indicator[C_LINK] check only runs when the buffer is live.
> * tests/ls/color-symlink-target.sh: New test.
> * tests/local.mk (all_tests): Add it.
> * NEWS: Mention the fix.
>
> Link: https://github.com/coreutils/coreutils/pull/352
> ---
>  NEWS                             |  4 ++++
>  src/ls.c                         |  1 +
>  tests/local.mk                   |  1 +
>  tests/ls/color-symlink-target.sh | 33 ++++++++++++++++++++++++++++++++
>  4 files changed, 39 insertions(+)
>  create mode 100755 tests/ls/color-symlink-target.sh

Thankfully, it seems pretty harmless. The bad read is the here:

    if (color_indicator[C_LINK].len == 6
        && !STRNCMP_LIT (color_indicator[C_LINK].string, "target"))
      color_symlink_as_referent = true;

Where STRNCMP_LIT expands to:

   strncmp (color_indicator[C_LINK].string, "target", 6)

and "color_indicator[C_LINK].string" is the just freed string that
previously contained a string constructed from the values parsed from
LS_COLORS.

But I agree it is worth applying before you make the release.

On a semi-related note, I've been a bit tempted to mess with the
--enable-single-binary code a bit to allow building a library with
ls_main, etc. That would make it possible to use LibFuzzer to try to
catch stuff like this. I expiremented a bit with AFL++, which seems
fine, but I suspect it is less efficient since it needs to execute a
process for each case.

Collin

Reply via email to