<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body><div style="font-family: sans-serif;"><div class="markdown" style="white-space: normal;">
<p dir="auto">On 31 Mar 2023, at 12:30, Remi Forax wrote:</p>
</div><div class="plaintext" style="white-space: normal;"><blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; color: #777777;"><p dir="auto">…
<br>
I agree that interpolate() is too easy to misuse but at the same time, it's a useful primitive.</p>
</blockquote></div>
<div class="markdown" style="white-space: normal;">
<p dir="auto">+1</p>
</div><div class="plaintext" style="white-space: normal;"><blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; color: #777777;"><p dir="auto">I wonder if the solution is to add an escape function, a function that takes an Object and returns an Object that should escape the values to interpolate.</p>
<p dir="auto">Something like
<br>
public String StringTemplate.interpolate(UnaryOperator<Object> escapeFunction) { ... }</p>
<p dir="auto">By asking for an escape function, we are making the API safer to use.</p>
</blockquote></div>
<div class="markdown" style="white-space: normal;">
<p dir="auto">But the workaround is saying <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">interpolate(x->x)</code> and grumbling about ceremony.  That workaround doesn’t get much closer to exposing the root problem.  Also, the unary operator, if we were to do this functionally as suggested, needs to “see” more context about each value that it would be interpolated.</p>
<p dir="auto">It seems to me that part of the problem here is the responsibility for escaping is on the wrong side of the fence, with <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">interpolate</code> as presently discussed.  When offered a function whose contract knows only about string joining, the party producing stringy bits to join into a correct DSL statement is burdened with responsibility of figuring out how and when to escape them, and in their various DSL-specific contexts.</p>
<p dir="auto">But surely that knowledge belongs more exactly to the ST processor, not to the supplier of interpolation values.  Some languages have context-dependent quoting rules.  Note that Remi’s suggested unary function doesn’t see the context.  It could be given context as <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">interpolate((x,c)->…)</code>, and that begs a very good question about the type of c.  What I’m saying is that c is not something the supplier of interpolation values should be forced to worry about.</p>
<p dir="auto">For example in SQL values are quoted with a single quote but names are quoted with a different kind of quote, often vendor-specific; yuck.  Fighting against code-injection might require getting the correct contextual flavor of quote in each case, if not for SQL then for more complex templated notations.  It’s lucky for SQL that textually doubling <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">'</code> to <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">''</code> will cover most use cases, regardless of context, but that’s just luck.  JSON has distinct kinds of values, which would require distinct tactics for validation and/or quoting; you need quote-escapes for string bodies and field names but not for numbers.  If you were trying to do Java templates you’d want to know the contextual difference between char and string literals.</p>
<p dir="auto">Generally speaking, getting the quoting right is not the direct responsibility directly of people supplying values to interpolate, but rather the responsibility of the party weaving together a (correct) template (SQL or JSON or …).  Asking the value-supplier to shoulder the burden of correct quoting requires a mix of two kinds of expertise (business logic and query syntax), which is how bugs happen.</p>
<p dir="auto">I think I would prefer to see a formulation of interpolate which would require users to take apart the ST processor, lower it into a plain-string-cat template processor, and then run a natively string-cat-ing format operation on it; after that it can be lifted back to its DSL, with fingers crossed that we got avoided bad injections.  But I admit I haven’t figured out the details, so that’s just a vague suggestion…</p>
<p dir="auto">What I hope is clear is my point about separating concerns, between knowing how and when to escape a value <em>in a particular place</em>, and coming up with a set of interpolation values for those places.  It’s rooted in the distinction between an envelope and its contents.  Quoting (and validation) is something envelope-specific.  Contents are usually specific to some completely unrelated domain of business logic.  Unless API users are helped to separate those concerns, there will be confusion, exploitable in attacks.</p>
<p dir="auto">— John</p>

</div></div></body>

</html>