Skip to main content

diesel/sqlite/connection/
limits.rs

1#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
2extern crate libsqlite3_sys as ffi;
3
4#[cfg(all(target_family = "wasm", target_os = "unknown"))]
5use sqlite_wasm_rs as ffi;
6
7use super::SqliteConnection;
8use crate::result::{DatabaseErrorKind, Error, QueryResult};
9use alloc::boxed::Box;
10use alloc::format;
11
12/// SQLite resource limits that can be configured per-connection.
13///
14/// These control aspects of SQLite's behavior and can be used to prevent
15/// resource exhaustion or limit query complexity.
16///
17/// Each variant exposes two associated constants: `DEFAULT_*_LIMIT` (SQLite's
18/// documented default) and `SAFE_*_LIMIT` (the hardened value applied by
19/// [`SqliteConnection::set_recommended_security_limits`](crate::sqlite::SqliteConnection::set_recommended_security_limits)).
20/// A connection's actual runtime default can differ from `DEFAULT_*_LIMIT`
21/// because some builds raise the compile-time maximum (for example the bundled
22/// `libsqlite3-sys` raises `FunctionArg` and `VariableNumber`).
23///
24/// See the [SQLite documentation](https://www.sqlite.org/c3ref/limit.html) for details.
25#[derive(#[automatically_derived]impl ::core::fmt::Debug for SqliteLimit {
    #[inline]
    #[rustc_trivial_field_reads]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_c_like_enum_write_str(f,
            "Length SqlLength ColumnCount ExprDepth CompoundSelect VdbeOp FunctionArg Attached LikePatternLength VariableNumber TriggerDepth WorkerThreads",
            match self {
                SqliteLimit::Length => 0usize,
                SqliteLimit::SqlLength => 7usize,
                SqliteLimit::ColumnCount => 17usize,
                SqliteLimit::ExprDepth => 29usize,
                SqliteLimit::CompoundSelect => 39usize,
                SqliteLimit::VdbeOp => 54usize,
                SqliteLimit::FunctionArg => 61usize,
                SqliteLimit::Attached => 73usize,
                SqliteLimit::LikePatternLength => 82usize,
                SqliteLimit::VariableNumber => 100usize,
                SqliteLimit::TriggerDepth => 115usize,
                SqliteLimit::WorkerThreads => 128usize,
            })
    }
}Debug, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for SqliteLimit {
}
#[automatically_derived]impl ::core::clone::Clone for SqliteLimit {
    #[inline]
    #[rustc_trivial_field_reads]
    fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]impl ::core::marker::Copy for SqliteLimit { }Copy, #[automatically_derived]impl ::core::marker::StructuralPartialEq for
    SqliteLimit {
}
#[automatically_derived]impl ::core::cmp::PartialEq for SqliteLimit {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        ::core::intrinsics::discriminant_value(self) ==
            ::core::intrinsics::discriminant_value(other)
    }
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for SqliteLimit { }Eq, #[automatically_derived]impl ::core::hash::Hash for SqliteLimit {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self),
            state)
    }
}Hash)]
26#[non_exhaustive]
27pub enum SqliteLimit {
28    /// Maximum length of any string or BLOB or table row, in bytes.
29    ///
30    /// See [`DEFAULT_LENGTH_LIMIT`](Self::DEFAULT_LENGTH_LIMIT) and
31    /// [`SAFE_LENGTH_LIMIT`](Self::SAFE_LENGTH_LIMIT).
32    Length,
33
34    /// Maximum length of an SQL statement, in bytes.
35    ///
36    /// See [`DEFAULT_SQL_LENGTH_LIMIT`](Self::DEFAULT_SQL_LENGTH_LIMIT) and
37    /// [`SAFE_SQL_LENGTH_LIMIT`](Self::SAFE_SQL_LENGTH_LIMIT).
38    SqlLength,
39
40    /// Maximum number of columns in a table definition, result set, or index,
41    /// and also the maximum number of columns in the ORDER BY or GROUP BY
42    /// clauses.
43    ///
44    /// See [`DEFAULT_COLUMN_COUNT_LIMIT`](Self::DEFAULT_COLUMN_COUNT_LIMIT) and
45    /// [`SAFE_COLUMN_COUNT_LIMIT`](Self::SAFE_COLUMN_COUNT_LIMIT).
46    ColumnCount,
47
48    /// Maximum depth of the parse tree for any expression.
49    ///
50    /// This can help prevent stack overflow from deeply nested expressions.
51    ///
52    /// See [`DEFAULT_EXPR_DEPTH_LIMIT`](Self::DEFAULT_EXPR_DEPTH_LIMIT) and
53    /// [`SAFE_EXPR_DEPTH_LIMIT`](Self::SAFE_EXPR_DEPTH_LIMIT).
54    ExprDepth,
55
56    /// Maximum number of terms in a compound SELECT statement.
57    ///
58    /// See [`DEFAULT_COMPOUND_SELECT_LIMIT`](Self::DEFAULT_COMPOUND_SELECT_LIMIT)
59    /// and [`SAFE_COMPOUND_SELECT_LIMIT`](Self::SAFE_COMPOUND_SELECT_LIMIT).
60    CompoundSelect,
61
62    /// Maximum number of instructions in a virtual machine program used to
63    /// implement an SQL statement.
64    ///
65    /// If [`sqlite3_prepare_v2()`](https://www.sqlite.org/c3ref/prepare.html)
66    /// or the equivalent tries to allocate space for more than this many
67    /// opcodes in a single prepared statement, an `SQLITE_NOMEM` error is
68    /// returned.
69    ///
70    /// See [`DEFAULT_VDBE_OP_LIMIT`](Self::DEFAULT_VDBE_OP_LIMIT) and
71    /// [`SAFE_VDBE_OP_LIMIT`](Self::SAFE_VDBE_OP_LIMIT).
72    VdbeOp,
73
74    /// Maximum number of arguments on a function.
75    ///
76    /// See [`DEFAULT_FUNCTION_ARG_LIMIT`](Self::DEFAULT_FUNCTION_ARG_LIMIT) and
77    /// [`SAFE_FUNCTION_ARG_LIMIT`](Self::SAFE_FUNCTION_ARG_LIMIT).
78    FunctionArg,
79
80    /// Maximum number of attached databases.
81    ///
82    /// See [`DEFAULT_ATTACHED_LIMIT`](Self::DEFAULT_ATTACHED_LIMIT) and
83    /// [`SAFE_ATTACHED_LIMIT`](Self::SAFE_ATTACHED_LIMIT).
84    Attached,
85
86    /// Maximum length of the pattern argument to the
87    /// [`LIKE`](https://www.sqlite.org/lang_expr.html#like) or
88    /// [`GLOB`](https://www.sqlite.org/lang_expr.html#glob) operators.
89    ///
90    /// See [`DEFAULT_LIKE_PATTERN_LENGTH_LIMIT`](Self::DEFAULT_LIKE_PATTERN_LENGTH_LIMIT)
91    /// and [`SAFE_LIKE_PATTERN_LENGTH_LIMIT`](Self::SAFE_LIKE_PATTERN_LENGTH_LIMIT).
92    LikePatternLength,
93
94    /// Maximum index number of any parameter in an SQL statement.
95    ///
96    /// See [`DEFAULT_VARIABLE_NUMBER_LIMIT`](Self::DEFAULT_VARIABLE_NUMBER_LIMIT)
97    /// and [`SAFE_VARIABLE_NUMBER_LIMIT`](Self::SAFE_VARIABLE_NUMBER_LIMIT).
98    VariableNumber,
99
100    /// Maximum recursion depth of triggers.
101    ///
102    /// See [`DEFAULT_TRIGGER_DEPTH_LIMIT`](Self::DEFAULT_TRIGGER_DEPTH_LIMIT) and
103    /// [`SAFE_TRIGGER_DEPTH_LIMIT`](Self::SAFE_TRIGGER_DEPTH_LIMIT).
104    TriggerDepth,
105
106    /// Maximum number of auxiliary worker threads that a single prepared
107    /// statement may start.
108    ///
109    /// See [`DEFAULT_WORKER_THREADS_LIMIT`](Self::DEFAULT_WORKER_THREADS_LIMIT)
110    /// and [`SAFE_WORKER_THREADS_LIMIT`](Self::SAFE_WORKER_THREADS_LIMIT).
111    WorkerThreads,
112}
113
114impl SqliteLimit {
115    /// SQLite's default for [`Length`](Self::Length).
116    pub const DEFAULT_LENGTH_LIMIT: u32 = 1_000_000_000;
117    /// Hardened value for [`Length`](Self::Length).
118    pub const SAFE_LENGTH_LIMIT: u32 = 1_000_000;
119
120    /// SQLite's default for [`SqlLength`](Self::SqlLength).
121    pub const DEFAULT_SQL_LENGTH_LIMIT: u32 = 1_000_000_000;
122    /// Hardened value for [`SqlLength`](Self::SqlLength).
123    pub const SAFE_SQL_LENGTH_LIMIT: u32 = 100_000;
124
125    /// SQLite's default for [`ColumnCount`](Self::ColumnCount).
126    pub const DEFAULT_COLUMN_COUNT_LIMIT: u32 = 2_000;
127    /// Hardened value for [`ColumnCount`](Self::ColumnCount).
128    pub const SAFE_COLUMN_COUNT_LIMIT: u32 = 100;
129
130    /// SQLite's default for [`ExprDepth`](Self::ExprDepth).
131    pub const DEFAULT_EXPR_DEPTH_LIMIT: u32 = 1_000;
132    /// Hardened value for [`ExprDepth`](Self::ExprDepth).
133    pub const SAFE_EXPR_DEPTH_LIMIT: u32 = 10;
134
135    /// SQLite's default for [`CompoundSelect`](Self::CompoundSelect).
136    pub const DEFAULT_COMPOUND_SELECT_LIMIT: u32 = 500;
137    /// Hardened value for [`CompoundSelect`](Self::CompoundSelect).
138    pub const SAFE_COMPOUND_SELECT_LIMIT: u32 = 3;
139
140    /// SQLite's default for [`VdbeOp`](Self::VdbeOp).
141    pub const DEFAULT_VDBE_OP_LIMIT: u32 = 250_000_000;
142    /// Hardened value for [`VdbeOp`](Self::VdbeOp).
143    pub const SAFE_VDBE_OP_LIMIT: u32 = 25_000;
144
145    /// SQLite's default for [`FunctionArg`](Self::FunctionArg).
146    pub const DEFAULT_FUNCTION_ARG_LIMIT: u32 = 127;
147    /// Hardened value for [`FunctionArg`](Self::FunctionArg).
148    pub const SAFE_FUNCTION_ARG_LIMIT: u32 = 8;
149
150    /// SQLite's default for [`Attached`](Self::Attached).
151    pub const DEFAULT_ATTACHED_LIMIT: u32 = 10;
152    /// Hardened value for [`Attached`](Self::Attached).
153    pub const SAFE_ATTACHED_LIMIT: u32 = 0;
154
155    /// SQLite's default for [`LikePatternLength`](Self::LikePatternLength).
156    pub const DEFAULT_LIKE_PATTERN_LENGTH_LIMIT: u32 = 50_000;
157    /// Hardened value for [`LikePatternLength`](Self::LikePatternLength).
158    pub const SAFE_LIKE_PATTERN_LENGTH_LIMIT: u32 = 50;
159
160    /// SQLite's published default for [`VariableNumber`](Self::VariableNumber).
161    ///
162    /// A particular build may compile a different maximum. The default
163    /// `libsqlite3-sys` bundle sets `SQLITE_MAX_VARIABLE_NUMBER=250000`, so a
164    /// connection's runtime default can exceed this published value.
165    pub const DEFAULT_VARIABLE_NUMBER_LIMIT: u32 = 32_766;
166    /// Hardened value for [`VariableNumber`](Self::VariableNumber).
167    pub const SAFE_VARIABLE_NUMBER_LIMIT: u32 = 10;
168
169    /// SQLite's default for [`TriggerDepth`](Self::TriggerDepth).
170    pub const DEFAULT_TRIGGER_DEPTH_LIMIT: u32 = 1_000;
171    /// Hardened value for [`TriggerDepth`](Self::TriggerDepth).
172    pub const SAFE_TRIGGER_DEPTH_LIMIT: u32 = 10;
173
174    /// SQLite's default for [`WorkerThreads`](Self::WorkerThreads).
175    pub const DEFAULT_WORKER_THREADS_LIMIT: u32 = 0;
176    /// Hardened value for [`WorkerThreads`](Self::WorkerThreads), equal to its
177    /// default, so the recommended setter leaves it untouched.
178    pub const SAFE_WORKER_THREADS_LIMIT: u32 = 0;
179
180    /// Convert to the corresponding FFI constant value.
181    pub(super) fn to_ffi(self) -> i32 {
182        match self {
183            SqliteLimit::Length => ffi::SQLITE_LIMIT_LENGTH,
184            SqliteLimit::SqlLength => ffi::SQLITE_LIMIT_SQL_LENGTH,
185            SqliteLimit::ColumnCount => ffi::SQLITE_LIMIT_COLUMN,
186            SqliteLimit::ExprDepth => ffi::SQLITE_LIMIT_EXPR_DEPTH,
187            SqliteLimit::CompoundSelect => ffi::SQLITE_LIMIT_COMPOUND_SELECT,
188            SqliteLimit::VdbeOp => ffi::SQLITE_LIMIT_VDBE_OP,
189            SqliteLimit::FunctionArg => ffi::SQLITE_LIMIT_FUNCTION_ARG,
190            SqliteLimit::Attached => ffi::SQLITE_LIMIT_ATTACHED,
191            SqliteLimit::LikePatternLength => ffi::SQLITE_LIMIT_LIKE_PATTERN_LENGTH,
192            SqliteLimit::VariableNumber => ffi::SQLITE_LIMIT_VARIABLE_NUMBER,
193            SqliteLimit::TriggerDepth => ffi::SQLITE_LIMIT_TRIGGER_DEPTH,
194            SqliteLimit::WorkerThreads => ffi::SQLITE_LIMIT_WORKER_THREADS,
195        }
196    }
197}
198
199impl SqliteConnection {
200    /// Set a runtime limit for this connection, returning its previous value.
201    ///
202    /// Lowering these limits is a way to harden a connection against untrusted
203    /// SQL. See the [SQLite documentation](https://www.sqlite.org/c3ref/limit.html)
204    /// for the meaning of each [`SqliteLimit`].
205    ///
206    /// # Errors
207    ///
208    /// Returns an error and leaves the limit unchanged when SQLite applies a
209    /// different value, which it does above its compile-time bound.
210    ///
211    /// # Example
212    ///
213    /// ```rust
214    /// # include!("../../doctest_setup.rs");
215    /// # fn main() { run_test(); }
216    /// # fn run_test() {
217    /// use diesel::sqlite::SqliteLimit;
218    ///
219    /// let mut conn = SqliteConnection::establish(":memory:").unwrap();
220    ///
221    /// // Cap SQL statement length at 1 KiB, keeping the previous value.
222    /// let previous = conn.set_limit(SqliteLimit::SqlLength, 1024).unwrap();
223    /// assert!(previous > 0);
224    /// assert_eq!(conn.get_limit(SqliteLimit::SqlLength), 1024);
225    /// # }
226    /// ```
227    pub fn set_limit(&mut self, limit: SqliteLimit, value: u32) -> QueryResult<u32> {
228        let previous = self.raw_connection.set_limit(limit, value);
229        let applied = self.raw_connection.get_limit(limit);
230        if applied == value {
231            return Ok(previous);
232        }
233        self.raw_connection.set_limit(limit, previous);
234        Err(Error::DatabaseError(
235            DatabaseErrorKind::Unknown,
236            Box::new(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("SQLite caps the {0:?} limit at {1}, below the requested {2}",
                limit, applied, value))
    })format!(
237                "SQLite caps the {limit:?} limit at {applied}, below the requested {value}"
238            )),
239        ))
240    }
241
242    /// Get the current value of a runtime limit for this connection.
243    ///
244    /// See the [SQLite documentation](https://www.sqlite.org/c3ref/limit.html)
245    /// for the meaning of each [`SqliteLimit`].
246    ///
247    /// # Example
248    ///
249    /// ```rust
250    /// # include!("../../doctest_setup.rs");
251    /// # fn main() { run_test(); }
252    /// # fn run_test() {
253    /// use diesel::sqlite::SqliteLimit;
254    ///
255    /// let conn = SqliteConnection::establish(":memory:").unwrap();
256    /// assert!(conn.get_limit(SqliteLimit::SqlLength) > 0);
257    /// # }
258    /// ```
259    pub fn get_limit(&self, limit: SqliteLimit) -> u32 {
260        self.raw_connection.get_limit(limit)
261    }
262
263    /// Apply SQLite's recommended limits for hardening against untrusted SQL.
264    ///
265    /// These are the values from the "Untrusted SQL Inputs" table of SQLite's
266    /// [security documentation](https://sqlite.org/security.html). They are
267    /// intentionally restrictive, so call [`set_limit`](Self::set_limit)
268    /// afterwards to relax any that are too aggressive for your application.
269    ///
270    /// | Limit | Value |
271    /// |-------|-------|
272    /// | `Length` | 1,000,000 |
273    /// | `SqlLength` | 100,000 |
274    /// | `ColumnCount` | 100 |
275    /// | `ExprDepth` | 10 |
276    /// | `CompoundSelect` | 3 |
277    /// | `VdbeOp` | 25,000 |
278    /// | `FunctionArg` | 8 |
279    /// | `Attached` | 0 |
280    /// | `LikePatternLength` | 50 |
281    /// | `VariableNumber` | 10 |
282    /// | `TriggerDepth` | 10 |
283    ///
284    /// The table's `PARSER_DEPTH` recommendation is omitted because it is a
285    /// compile-time only setting with no runtime `sqlite3_limit()` category.
286    /// `WorkerThreads` is left untouched (its default of 0 is already safe).
287    ///
288    /// # Errors
289    ///
290    /// Returns an error if SQLite rejects one of the values, as [`set_limit`](Self::set_limit) does.
291    ///
292    /// # Example
293    ///
294    /// ```rust
295    /// # include!("../../doctest_setup.rs");
296    /// # fn main() { run_test(); }
297    /// # fn run_test() {
298    /// use diesel::sqlite::SqliteLimit;
299    ///
300    /// let mut conn = SqliteConnection::establish(":memory:").unwrap();
301    /// conn.set_recommended_security_limits().unwrap();
302    /// assert_eq!(conn.get_limit(SqliteLimit::SqlLength), 100_000);
303    ///
304    /// // Relax an individual limit that is too strict for this application.
305    /// conn.set_limit(SqliteLimit::VariableNumber, 999).unwrap();
306    /// assert_eq!(conn.get_limit(SqliteLimit::VariableNumber), 999);
307    /// # }
308    /// ```
309    pub fn set_recommended_security_limits(&mut self) -> QueryResult<()> {
310        self.set_limit(SqliteLimit::Length, SqliteLimit::SAFE_LENGTH_LIMIT)?;
311        self.set_limit(SqliteLimit::SqlLength, SqliteLimit::SAFE_SQL_LENGTH_LIMIT)?;
312        self.set_limit(
313            SqliteLimit::ColumnCount,
314            SqliteLimit::SAFE_COLUMN_COUNT_LIMIT,
315        )?;
316        self.set_limit(SqliteLimit::ExprDepth, SqliteLimit::SAFE_EXPR_DEPTH_LIMIT)?;
317        self.set_limit(
318            SqliteLimit::CompoundSelect,
319            SqliteLimit::SAFE_COMPOUND_SELECT_LIMIT,
320        )?;
321        self.set_limit(SqliteLimit::VdbeOp, SqliteLimit::SAFE_VDBE_OP_LIMIT)?;
322        self.set_limit(
323            SqliteLimit::FunctionArg,
324            SqliteLimit::SAFE_FUNCTION_ARG_LIMIT,
325        )?;
326        self.set_limit(SqliteLimit::Attached, SqliteLimit::SAFE_ATTACHED_LIMIT)?;
327        self.set_limit(
328            SqliteLimit::LikePatternLength,
329            SqliteLimit::SAFE_LIKE_PATTERN_LENGTH_LIMIT,
330        )?;
331        self.set_limit(
332            SqliteLimit::VariableNumber,
333            SqliteLimit::SAFE_VARIABLE_NUMBER_LIMIT,
334        )?;
335        self.set_limit(
336            SqliteLimit::TriggerDepth,
337            SqliteLimit::SAFE_TRIGGER_DEPTH_LIMIT,
338        )?;
339        Ok(())
340    }
341}
342
343#[cfg(test)]
344mod tests {
345    use super::*;
346    use crate::prelude::*;
347
348    fn connection() -> SqliteConnection {
349        SqliteConnection::establish(":memory:").unwrap()
350    }
351
352    #[diesel_test_helper::test]
353    fn set_limit_returns_previous_value() {
354        let mut conn = connection();
355        let original = conn.get_limit(SqliteLimit::SqlLength);
356
357        // Setting a new value returns the old one, and a second set returns the
358        // value installed by the first.
359        assert_eq!(
360            conn.set_limit(SqliteLimit::SqlLength, 1024).unwrap(),
361            original
362        );
363        assert_eq!(conn.set_limit(SqliteLimit::SqlLength, 2048).unwrap(), 1024);
364        assert_eq!(conn.get_limit(SqliteLimit::SqlLength), 2048);
365    }
366
367    #[diesel_test_helper::test]
368    fn get_limit_does_not_mutate() {
369        let conn = connection();
370        let first = conn.get_limit(SqliteLimit::ExprDepth);
371        // Querying is implemented by passing -1 to sqlite3_limit, which must
372        // leave the limit unchanged.
373        assert!(first > 0);
374        assert_eq!(conn.get_limit(SqliteLimit::ExprDepth), first);
375    }
376
377    #[diesel_test_helper::test]
378    fn set_limit_enforces_length() {
379        let mut conn = connection();
380        conn.set_limit(SqliteLimit::Length, 100).unwrap();
381
382        assert!(
383            crate::sql_query("SELECT length(randomblob(50))")
384                .execute(&mut conn)
385                .is_ok()
386        );
387        if cfg!(not(miri)) {
388            // ffi string access
389            // A 500-byte blob exceeds the 100-byte row/value limit ("string or blob too big").
390            assert!(
391                crate::sql_query("SELECT length(randomblob(500))")
392                    .execute(&mut conn)
393                    .is_err()
394            );
395        }
396    }
397
398    #[diesel_test_helper::test]
399    fn set_limit_enforces_column_count() {
400        // A wide result set runs under the default column limit but fails once the limit is
401        // lowered below its column count ("too many columns in result set").
402        let wide = format!(
403            "SELECT {}",
404            (1..=30)
405                .map(|i| i.to_string())
406                .collect::<Vec<_>>()
407                .join(", ")
408        );
409
410        let mut unconstrained = connection();
411        assert!(crate::sql_query(&wide).execute(&mut unconstrained).is_ok());
412
413        if cfg!(not(miri)) {
414            // ffi string access
415            let mut conn = connection();
416            conn.set_limit(SqliteLimit::ColumnCount, 10).unwrap();
417            assert!(crate::sql_query(&wide).execute(&mut conn).is_err());
418        }
419    }
420
421    #[diesel_test_helper::test]
422    fn set_limit_enforces_expr_depth() {
423        let mut conn = connection();
424        conn.set_limit(SqliteLimit::ExprDepth, 5).unwrap();
425
426        assert!(crate::sql_query("SELECT 1+1").execute(&mut conn).is_ok());
427        if cfg!(not(miri)) {
428            // ffi string access
429            // A 40-deep addition tree exceeds the parse-tree depth of five.
430            let deep = format!("SELECT {}1", "1+".repeat(40));
431            assert!(crate::sql_query(&deep).execute(&mut conn).is_err());
432        }
433    }
434
435    #[diesel_test_helper::test]
436    fn set_limit_enforces_compound_select() {
437        let mut conn = connection();
438        conn.set_limit(SqliteLimit::CompoundSelect, 2).unwrap();
439
440        assert!(
441            crate::sql_query("SELECT 1 UNION SELECT 2")
442                .execute(&mut conn)
443                .is_ok()
444        );
445        if cfg!(not(miri)) {
446            // ffi string access
447            // Five UNION terms exceed the limit of two ("too many terms in compound SELECT").
448            assert!(
449                crate::sql_query(
450                    "SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5"
451                )
452                .execute(&mut conn)
453                .is_err()
454            );
455        }
456    }
457
458    #[diesel_test_helper::test]
459    fn set_limit_enforces_vdbe_op() {
460        // The same heavy statement runs under the default opcode budget but fails once that
461        // budget is restricted to a tiny value (reported as SQLITE_NOMEM).
462        let heavy = "SELECT count(*) FROM sqlite_master a, sqlite_master b, sqlite_master c";
463
464        let mut unconstrained = connection();
465        assert!(crate::sql_query(heavy).execute(&mut unconstrained).is_ok());
466
467        if cfg!(not(miri)) {
468            // ffi string access
469            let mut conn = connection();
470            conn.set_limit(SqliteLimit::VdbeOp, 5).unwrap();
471            assert!(crate::sql_query(heavy).execute(&mut conn).is_err());
472        }
473    }
474
475    #[diesel_test_helper::test]
476    fn set_limit_enforces_function_arg() {
477        let mut conn = connection();
478        conn.set_limit(SqliteLimit::FunctionArg, 3).unwrap();
479
480        assert!(
481            crate::sql_query("SELECT max(1, 2, 3)")
482                .execute(&mut conn)
483                .is_ok()
484        );
485        if cfg!(not(miri)) {
486            // ffi string access
487            // Eight arguments exceed the limit of three ("too many arguments on function max").
488            assert!(
489                crate::sql_query("SELECT max(1, 2, 3, 4, 5, 6, 7, 8)")
490                    .execute(&mut conn)
491                    .is_err()
492            );
493        }
494    }
495
496    #[cfg(not(miri))] // ffi string access
497    #[diesel_test_helper::test]
498    fn set_limit_enforces_attached() {
499        let mut conn = connection();
500        conn.set_limit(SqliteLimit::Attached, 0).unwrap();
501
502        // With zero attachments allowed, any ATTACH is rejected ("too many attached databases").
503        assert!(
504            crate::sql_query("ATTACH DATABASE ':memory:' AS aux_db")
505                .execute(&mut conn)
506                .is_err()
507        );
508    }
509
510    #[diesel_test_helper::test]
511    fn set_limit_enforces_variable_number() {
512        let mut conn = connection();
513        let limit = 10;
514
515        // The published default sits below the bundled ceiling, so it is applied verbatim and
516        // acts as the boundary: a parameter index at the limit is accepted, one past it is
517        // rejected ("variable number must be between ?1 and ?N").
518        conn.set_limit(SqliteLimit::VariableNumber, 10).unwrap();
519        let at_limit = format!("SELECT ?{}", limit);
520        let mut at_limit_query = crate::sql_query(&at_limit).into_boxed();
521        for _ in 0..limit {
522            at_limit_query = at_limit_query.bind::<crate::sql_types::Integer, _>(1);
523        }
524        let past_limit = format!("SELECT ?{}", limit + 1);
525        let mut past_limit_query = crate::sql_query(&past_limit).into_boxed();
526        for _ in 0..(limit + 1) {
527            past_limit_query = past_limit_query.bind::<crate::sql_types::Integer, _>(1);
528        }
529
530        assert!(at_limit_query.execute(&mut conn).is_ok());
531        if cfg!(not(miri)) {
532            // ffi string access
533            assert!(past_limit_query.execute(&mut conn).is_err());
534        }
535    }
536
537    #[diesel_test_helper::test]
538    fn set_limit_enforces_trigger_depth() {
539        use crate::connection::SimpleConnection;
540
541        // A recursive trigger that terminates on its own at x = 100.
542        let setup = "PRAGMA recursive_triggers = ON;\
543             CREATE TABLE recur (x INTEGER);\
544             CREATE TRIGGER recur_tr AFTER INSERT ON recur WHEN NEW.x < 100 \
545             BEGIN INSERT INTO recur VALUES (NEW.x + 1); END;";
546
547        // Under the default depth the recursion completes.
548        let mut unconstrained = connection();
549        unconstrained.batch_execute(setup).unwrap();
550        assert!(
551            crate::sql_query("INSERT INTO recur VALUES (1)")
552                .execute(&mut unconstrained)
553                .is_ok()
554        );
555
556        // A tiny depth limit is hit before the recursion can terminate
557        // ("too many levels of trigger recursion").
558        let mut conn = connection();
559        conn.set_limit(SqliteLimit::TriggerDepth, 3).unwrap();
560        conn.batch_execute(setup).unwrap();
561        if cfg!(not(miri)) {
562            // ffi string access
563            assert!(
564                crate::sql_query("INSERT INTO recur VALUES (1)")
565                    .execute(&mut conn)
566                    .is_err()
567            );
568        }
569    }
570
571    #[diesel_test_helper::test]
572    fn worker_threads_limit_has_no_runtime_error_path() {
573        // Unlike the other categories, WorkerThreads only caps the number of auxiliary sort
574        // threads a statement may start. Lowering it never raises an error, it only affects
575        // performance. There is therefore no enforcement failure to assert, only that the value
576        // is applied and ordinary queries keep working.
577        let mut conn = connection();
578        conn.set_limit(SqliteLimit::WorkerThreads, 0).unwrap();
579        assert_eq!(conn.get_limit(SqliteLimit::WorkerThreads), 0);
580        assert!(crate::sql_query("SELECT 1").execute(&mut conn).is_ok());
581    }
582
583    #[cfg(not(miri))]
584    #[diesel_test_helper::test]
585    fn set_limit_enforces_sql_length() {
586        let mut conn = connection();
587        conn.set_limit(SqliteLimit::SqlLength, 20).unwrap();
588
589        // A statement longer than 20 bytes is rejected by SQLite.
590        let result =
591            crate::sql_query("SELECT * FROM sqlite_master WHERE type = 'table'").execute(&mut conn);
592        assert!(result.is_err());
593    }
594
595    #[diesel_test_helper::test]
596    fn set_limit_enforces_like_pattern_length() {
597        let mut conn = connection();
598        conn.set_limit(SqliteLimit::LikePatternLength, 100).unwrap();
599
600        assert!(
601            crate::sql_query("SELECT 'test' LIKE 'te%'")
602                .execute(&mut conn)
603                .is_ok()
604        );
605
606        // ffi string access
607        if cfg!(not(miri)) {
608            let long_pattern = "%".repeat(200);
609            let query = format!("SELECT 'test' LIKE '{long_pattern}'");
610            assert!(crate::sql_query(&query).execute(&mut conn).is_err());
611        }
612    }
613
614    #[diesel_test_helper::test]
615    fn set_limit_rejects_values_above_compile_time_maximum() {
616        let mut conn = connection();
617        conn.set_limit(SqliteLimit::Length, 100).unwrap();
618        // SQLite would clamp to its compile-time ceiling, which is reported instead of applied.
619        assert!(conn.set_limit(SqliteLimit::Length, u32::MAX).is_err());
620        assert_eq!(conn.get_limit(SqliteLimit::Length), 100);
621    }
622
623    #[diesel_test_helper::test]
624    fn set_recommended_security_limits_applies_documented_table() {
625        let mut conn = connection();
626        conn.set_recommended_security_limits().unwrap();
627
628        assert_eq!(conn.get_limit(SqliteLimit::Length), 1_000_000);
629        assert_eq!(conn.get_limit(SqliteLimit::SqlLength), 100_000);
630        assert_eq!(conn.get_limit(SqliteLimit::ColumnCount), 100);
631        assert_eq!(conn.get_limit(SqliteLimit::ExprDepth), 10);
632        assert_eq!(conn.get_limit(SqliteLimit::CompoundSelect), 3);
633        assert_eq!(conn.get_limit(SqliteLimit::VdbeOp), 25_000);
634        assert_eq!(conn.get_limit(SqliteLimit::FunctionArg), 8);
635        assert_eq!(conn.get_limit(SqliteLimit::Attached), 0);
636        assert_eq!(conn.get_limit(SqliteLimit::LikePatternLength), 50);
637        assert_eq!(conn.get_limit(SqliteLimit::VariableNumber), 10);
638        assert_eq!(conn.get_limit(SqliteLimit::TriggerDepth), 10);
639    }
640
641    #[diesel_test_helper::test]
642    fn safe_limit_constants_do_not_exceed_defaults() {
643        // The hardened value for each category is a tightening of SQLite's published default, so
644        // it must never be larger. This is asserted instead of comparing the `DEFAULT_*`
645        // constants to a fresh connection, because the runtime default of categories such as
646        // `FunctionArg` and `VariableNumber` is build-dependent (the bundled libsqlite3-sys
647        // raises several of them), while these published constants are fixed.
648        let pairs = [
649            (
650                SqliteLimit::SAFE_LENGTH_LIMIT,
651                SqliteLimit::DEFAULT_LENGTH_LIMIT,
652            ),
653            (
654                SqliteLimit::SAFE_SQL_LENGTH_LIMIT,
655                SqliteLimit::DEFAULT_SQL_LENGTH_LIMIT,
656            ),
657            (
658                SqliteLimit::SAFE_COLUMN_COUNT_LIMIT,
659                SqliteLimit::DEFAULT_COLUMN_COUNT_LIMIT,
660            ),
661            (
662                SqliteLimit::SAFE_EXPR_DEPTH_LIMIT,
663                SqliteLimit::DEFAULT_EXPR_DEPTH_LIMIT,
664            ),
665            (
666                SqliteLimit::SAFE_COMPOUND_SELECT_LIMIT,
667                SqliteLimit::DEFAULT_COMPOUND_SELECT_LIMIT,
668            ),
669            (
670                SqliteLimit::SAFE_VDBE_OP_LIMIT,
671                SqliteLimit::DEFAULT_VDBE_OP_LIMIT,
672            ),
673            (
674                SqliteLimit::SAFE_FUNCTION_ARG_LIMIT,
675                SqliteLimit::DEFAULT_FUNCTION_ARG_LIMIT,
676            ),
677            (
678                SqliteLimit::SAFE_ATTACHED_LIMIT,
679                SqliteLimit::DEFAULT_ATTACHED_LIMIT,
680            ),
681            (
682                SqliteLimit::SAFE_LIKE_PATTERN_LENGTH_LIMIT,
683                SqliteLimit::DEFAULT_LIKE_PATTERN_LENGTH_LIMIT,
684            ),
685            (
686                SqliteLimit::SAFE_VARIABLE_NUMBER_LIMIT,
687                SqliteLimit::DEFAULT_VARIABLE_NUMBER_LIMIT,
688            ),
689            (
690                SqliteLimit::SAFE_TRIGGER_DEPTH_LIMIT,
691                SqliteLimit::DEFAULT_TRIGGER_DEPTH_LIMIT,
692            ),
693            (
694                SqliteLimit::SAFE_WORKER_THREADS_LIMIT,
695                SqliteLimit::DEFAULT_WORKER_THREADS_LIMIT,
696            ),
697        ];
698        for (safe, default) in pairs {
699            assert!(
700                safe <= default,
701                "safe value {safe} exceeds default {default}"
702            );
703        }
704    }
705
706    #[diesel_test_helper::test]
707    fn safe_limit_constants_match_recommended_setter() {
708        let mut conn = connection();
709        conn.set_recommended_security_limits().unwrap();
710
711        assert_eq!(
712            conn.get_limit(SqliteLimit::Length),
713            SqliteLimit::SAFE_LENGTH_LIMIT
714        );
715        assert_eq!(
716            conn.get_limit(SqliteLimit::SqlLength),
717            SqliteLimit::SAFE_SQL_LENGTH_LIMIT
718        );
719        assert_eq!(
720            conn.get_limit(SqliteLimit::ColumnCount),
721            SqliteLimit::SAFE_COLUMN_COUNT_LIMIT
722        );
723        assert_eq!(
724            conn.get_limit(SqliteLimit::ExprDepth),
725            SqliteLimit::SAFE_EXPR_DEPTH_LIMIT
726        );
727        assert_eq!(
728            conn.get_limit(SqliteLimit::CompoundSelect),
729            SqliteLimit::SAFE_COMPOUND_SELECT_LIMIT
730        );
731        assert_eq!(
732            conn.get_limit(SqliteLimit::VdbeOp),
733            SqliteLimit::SAFE_VDBE_OP_LIMIT
734        );
735        assert_eq!(
736            conn.get_limit(SqliteLimit::FunctionArg),
737            SqliteLimit::SAFE_FUNCTION_ARG_LIMIT
738        );
739        assert_eq!(
740            conn.get_limit(SqliteLimit::Attached),
741            SqliteLimit::SAFE_ATTACHED_LIMIT
742        );
743        assert_eq!(
744            conn.get_limit(SqliteLimit::LikePatternLength),
745            SqliteLimit::SAFE_LIKE_PATTERN_LENGTH_LIMIT
746        );
747        assert_eq!(
748            conn.get_limit(SqliteLimit::VariableNumber),
749            SqliteLimit::SAFE_VARIABLE_NUMBER_LIMIT
750        );
751        assert_eq!(
752            conn.get_limit(SqliteLimit::TriggerDepth),
753            SqliteLimit::SAFE_TRIGGER_DEPTH_LIMIT
754        );
755        // The recommended setter leaves `WorkerThreads` untouched because its default is already
756        // safe, so assert that the documented safe value matches what the connection reports.
757        assert_eq!(
758            conn.get_limit(SqliteLimit::WorkerThreads),
759            SqliteLimit::SAFE_WORKER_THREADS_LIMIT
760        );
761    }
762}