确保参数是编译时定义的字符串文字

Max*_*888 3 string sql-injection string-literals rust

为了防止 SQL 注入的风险,我想创建一个 API,其中的函数只接受编译时字符串文字作为输入,例如"SELECT * FROM MYTABLE;""WHERE price > 10"等。然后该函数可以执行所需的字符串连接,生成Stringsql 语句并执行它。这将是执行 SQL 的唯一方法,因此它保证 SQL 语句仅从开发人员定义的 SQL 位创建,并且任何不受信任的用户输入都必须映射到字符串文字。这消除了用户输入最终出现在 SQL 语句中的任何可能性。这可能吗?

Cha*_*man 6

你可以采取&'static str。这并不能完全消除风险,例如由于String::leak()代码不安全,但这使得这种情况发生的可能性很小。

如果你真的想要,你可以有一个小宏:

#[derive(Clone, Copy)]
pub struct StringLiteral(&'static str);

impl StringLiteral {
    /// # Safety
    ///
    /// `v` must be a string literal.
    #[doc(hidden)]
    pub unsafe fn new(v: &'static str) -> Self {
        Self(v)
    }

    pub fn get(self) -> &'static str {
        self.0
    }
}

#[macro_export]
macro_rules! string_literal {
    ($v:literal) => {{
        let v = $v; // This has to be a separate statement, to not be in the `unsafe` block
        // SAFETY: We only accept literals.
        unsafe { $crate::StringLiteral::new(v) }
    }};
}
Run Code Online (Sandbox Code Playgroud)

然后在代码中的任何地方使用StringLiteral,这是不可能不从文字构造(合理地)的。