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