allenap / shell-quote

A Rust library for shell quoting strings, e.g. for interpolating into a Bash script. This is not as simple as most people think!
Apache License 2.0
5 stars 2 forks source link

`Sh` can produce non-UTF-8 byte strings, so is not safe to use with `String` #17

Closed allenap closed 3 months ago

allenap commented 3 months ago

There are two impls that assume that Quoters produce valid UTF-8:

impl<'a, S> QuoteRefExt<String> for S
where
    S: ?Sized + Into<Quotable<'a>>,
{
    fn quoted<Q: Quoter>(self, _q: Q) -> String {
        let quoted = Q::quote(self);
        // SAFETY: `quoted` is valid UTF-8 (ASCII, in truth) because it was
        // generated by a `quote` implementation from this crate –
        // enforced because `Quoter` is sealed.
        unsafe { String::from_utf8_unchecked(quoted) }
    }
}

and:

impl QuoteExt for String {
    fn push_quoted<'a, Q: Quoter, S: ?Sized + Into<Quotable<'a>>>(&mut self, _q: Q, s: S) {
        let quoted = Q::quote(s);
        // SAFETY: `quoted` is valid UTF-8 (ASCII, in truth) because it was
        // generated by a `quote` implementation from this crate –
        // enforced because `Quoter` is sealed.
        let quoted = unsafe { std::str::from_utf8_unchecked(&quoted) };
        self.push_str(quoted);
    }
}

However, the dash shell, which is the de facto /bin/sh in many places today, does not have escape sequences for bytes 0x7f to 0xff, so these are written directly. This change hit master recently (a3f5aac0fdd71c286d72d21078812ff437cc720e, #14).

This means that the impls above are not safe for use with Sh.