无法使用 FormattableString
Not able to use FormattableString
阅读 this interesting article 关于 EF Core 中的 SQL 注入预防,我发现现在内插字符串可能导致 FormattableString
.
运行 .NET Core 2.2 中的测试代码:
public static void Main()
{
var filter = "Mark'; DROP TABLE tbl; --";
Console.WriteLine(FromSql("SELECT * FROM tbl WHERE fld = '" + filter + "'"));
Console.WriteLine(FromSql($"SELECT * FROM tbl WHERE fld = {filter}"));
Console.WriteLine(FromSql(FormattableStringFactory.Create(
"SELECT * FROM tbl WHERE fld = {0}", filter)));
}
private static string FromSql(string sql) => sql;
private static string FromSql(FormattableString sql)
{
var formatArgs = sql.GetArguments();
for (var paramIndex = 0; paramIndex < sql.ArgumentCount; ++paramIndex)
formatArgs[paramIndex] = "@p" + paramIndex;
return sql.ToString();
}
没有达到我的预期:
SELECT * FROM tbl WHERE fld = 'Mark'; DROP TABLE tbl; --'
SELECT * FROM tbl WHERE fld = Mark'; DROP TABLE tbl; --
SELECT * FROM tbl WHERE fld = @p0
第二次打印应该像最后一次一样输出。
试试这个 fiddle。
我错过了什么?
你的第二个调用 Console.WriteLine(FromSql($"SELECT * FROM tbl WHERE fld = {filter}"));
看起来是去 FromSql(string sql)
重载而不是 FromSql(FormattableString sql)
。
只需删除 FromSql(string sql)
方法 (以及对它的第一次调用),
它将按预期进行;查看修改后的 Fiddle.
编译器似乎可以翻译
var q = $"SELECT * FROM tbl WHERE fld = {filter}";
到 string
.
String q = $"SELECT * FROM tbl WHERE fld = {filter}";`
由于 string
类型,发生了 String.Format
。
来自 documentation:
If an interpolated string has the type string, it's typically transformed into a String.Format method call .
而在
中明确指定 FormattableString
FormattableString q = $"SELECT * FROM tbl WHERE fld = {filter}";
正在使用 FormattableStringFactory.Create
。
来自 documentation:
If an interpolated string has the type IFormattable or FormattableString, the compiler generates a call to the FormattableStringFactory.Create method.
阅读 this interesting article 关于 EF Core 中的 SQL 注入预防,我发现现在内插字符串可能导致 FormattableString
.
运行 .NET Core 2.2 中的测试代码:
public static void Main()
{
var filter = "Mark'; DROP TABLE tbl; --";
Console.WriteLine(FromSql("SELECT * FROM tbl WHERE fld = '" + filter + "'"));
Console.WriteLine(FromSql($"SELECT * FROM tbl WHERE fld = {filter}"));
Console.WriteLine(FromSql(FormattableStringFactory.Create(
"SELECT * FROM tbl WHERE fld = {0}", filter)));
}
private static string FromSql(string sql) => sql;
private static string FromSql(FormattableString sql)
{
var formatArgs = sql.GetArguments();
for (var paramIndex = 0; paramIndex < sql.ArgumentCount; ++paramIndex)
formatArgs[paramIndex] = "@p" + paramIndex;
return sql.ToString();
}
没有达到我的预期:
SELECT * FROM tbl WHERE fld = 'Mark'; DROP TABLE tbl; --'
SELECT * FROM tbl WHERE fld = Mark'; DROP TABLE tbl; --
SELECT * FROM tbl WHERE fld = @p0
第二次打印应该像最后一次一样输出。
试试这个 fiddle。
我错过了什么?
你的第二个调用 Console.WriteLine(FromSql($"SELECT * FROM tbl WHERE fld = {filter}"));
看起来是去 FromSql(string sql)
重载而不是 FromSql(FormattableString sql)
。
只需删除 FromSql(string sql)
方法 (以及对它的第一次调用),
它将按预期进行;查看修改后的 Fiddle.
编译器似乎可以翻译
var q = $"SELECT * FROM tbl WHERE fld = {filter}";
到 string
.
String q = $"SELECT * FROM tbl WHERE fld = {filter}";`
由于 string
类型,发生了 String.Format
。
来自 documentation:
If an interpolated string has the type string, it's typically transformed into a String.Format method call .
而在
中明确指定FormattableString
FormattableString q = $"SELECT * FROM tbl WHERE fld = {filter}";
正在使用 FormattableStringFactory.Create
。
来自 documentation:
If an interpolated string has the type IFormattable or FormattableString, the compiler generates a call to the FormattableStringFactory.Create method.