-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Description
This code is safe:
db.ExecuteSqlCommand($"delete from Log where Time<{time}");
But this is not:
db.ExecuteSqlCommand(useLogA ?
$"delete from LogA where Time<{time}" :
$"delete from LogB where Time<{time}");
Likewise, this is not:
db.ExecuteSqlCommand(
$"delete from Log " +
$"where Time<{time}");
In the first unsafe case, when two FormattableString
operands are used with the conditional operator, the expression evaluates to a string, not another FormattableString
. Unless you know this subtle (and I find rather unintuitive) rule, you might easily write code expecting the argument to be passed as a SQL parameter, only to find you've really dumped unsanitized user content into a SQL command.
In the second unsafe case, you're using multiple lines for readability. If you're a big C# fan, you might think C# is awesome enough to use string literal concatenation with interpolated strings. You'll be extra disappointed when your evil hacker trim, who hates C#, thinks otherwise, and proves he's right by bringing down your site.
In both unsafe cases the implicit conversion from string to RawSqlString
causes the unintended overload to be invoked.
Proposed resolution:
- Long term: Improve C# string interpolation.
- Short term: Mark the
FormattableString
overload obsolete so that a warning alerts devs to the potential danger. Create a replacement that simply has a different name from theRawSqlString
overload, perhapsExecuteFormattedSqlCommand
.