Yeah, strong plus one here! To expand on this, it's important that we allow API like the following
use std::process::Command;
fn build_cmd(interpolated: InterpolatedArgs<???>) -> Command {
....
}
let branch = "my branch"
let cmd = build_cmd(i"git switch {branch}");
assert_eq!(cmd.get_args.count(), 3);
It should be possible to implement build_cmd
in a way that is not susceptible to shell injection. The problem is, I don't think we currently can spell-out a type for InterpolatedArgs
.
It's useful to take a look at JS here. They did the right thing here with tagged templates. When you write, in JS,
i`select from ${foo()} where id = ${bar};`
The user-defined i
function gets called roughly as i(["select from ", "where id =", ";"], [foo(), bar])
. That is, the user gets to apply custom escaping rules when processing the string.
The problem is, the second argument here is a heterogeneous list To support this in Rust, we need a language machinery to define InterpolatedArgs<Ts...>
and to define where
-clauses like where Ts...: SqlEscape
.
Today's format args work because they are specialized to one particular trait fmt::Display
and use dynamic dispatch.
I sadly don't see how we can solve a very practical problem of allowing injection-prof APIs without advanced type machinery And yeah, there is a danger that, by making string interpolation convenient enough without providing a more general mechanism as well, we'll end up with people using interpolation for things like SQL or HTML building.