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