Interpolated strings and SQL
Timon Gehr
timon.gehr at gmx.ch
Thu Jan 11 20:13:10 UTC 2024
On 1/10/24 01:03, Walter Bright wrote:
> On 1/9/2024 12:04 AM, Nickolay Bukreyev wrote:
>> I’ve just realized DIP1036 has an excellent feature that is not
>> evident right away. Look at the signature of `execi`:
>>
>> ```d
>> auto execi(Args...)(Sqlite db, InterpolationHeader header, Args args,
>> InterpolationFooter footer) { ... }
>> ```
>>
>> `InterpolationHeader`/`InterpolationFooter` _require_ you to pass an
>> istring. Consider this example:
>>
>> ```d
>> db.execi(i"INSERT INTO items VALUES ($(x))".text);
>> ```
>>
>> Here, we accidentally added `.text`. It would be an SQL injection… but
>> the compiler rejects it! `typeof(i"...".text)` is `string`, and
>> `execi` cannot be called with `(Sqlite, string)`.
>
> The compiler will indeed reject it (The error message would be a bit
> baffling to those who don't know what Interpolation types are), along
> with any attempt to call execi() with a pre-constructed string.
>
> The end result is that to do manipulation with istring tuples, the
> programmer is alternately faced with adding Interpolation elements or
> filtering them out. Is that really what we want?
What we want that DIP1036e mostly provides is:
0. The library can detect whether it is being passed an istring.
1. The library that accepts the istring decides how to process it.
2. The string parts of the istring are known to the library at compile time.
3. The expression parts of the istring can be evaluated only at runtime.
4. The expression parts of the istring can be passed arbitrarily, by
ref, lazy, alias, ... (this part in fact works better with DIP1027).
5. The library can access the original expression, e.g. in string form.
6. A templated function that is called with an istring can do all of the
above.
> Will that impede the use of tuples generally, or just impede the use of istrings?
> ...
It's just a way to achieve 0.-6. above relatively well with a simple
patch to the lexer. I am not sure why it would impede anything except
compile time and binary size.
> ---
>
> P.S. most keyboarding bugs result from neglecting to add needed syntax,
> not typing extra stuff. This is why:
>
> int* p;
>
> is initialized to zero, while:
>
> int* p = void;
>
> is left uninitialized. The user is unlikely to accidentally type "= void".
The user (especially the kind of user that may be prone to accidentally
introduce an SQL injection attack) is more likely to accidentally type
`.format` or `.text` because that may be a relatively common way to use
an istring in their code base.
More information about the Digitalmars-d
mailing list