@@ -140,30 +140,82 @@ Local<DictionaryTemplate> getLazyIterTemplate(Environment* env) {
140140} // namespace
141141
142142// Mapping from JavaScript property names to SQLite limit constants
143+ // Default compile-time maximums from SQLite (these match SQLite's defaults)
144+ #ifndef SQLITE_MAX_LENGTH
145+ #define SQLITE_MAX_LENGTH 1000000000
146+ #endif
147+ #ifndef SQLITE_MAX_SQL_LENGTH
148+ #define SQLITE_MAX_SQL_LENGTH 1000000000
149+ #endif
150+ #ifndef SQLITE_MAX_COLUMN
151+ #define SQLITE_MAX_COLUMN 2000
152+ #endif
153+ #ifndef SQLITE_MAX_EXPR_DEPTH
154+ #define SQLITE_MAX_EXPR_DEPTH 1000
155+ #endif
156+ #ifndef SQLITE_MAX_COMPOUND_SELECT
157+ #define SQLITE_MAX_COMPOUND_SELECT 500
158+ #endif
159+ #ifndef SQLITE_MAX_VDBE_OP
160+ #define SQLITE_MAX_VDBE_OP 250000000
161+ #endif
162+ #ifndef SQLITE_MAX_FUNCTION_ARG
163+ #define SQLITE_MAX_FUNCTION_ARG 1000
164+ #endif
165+ #ifndef SQLITE_MAX_ATTACHED
166+ #define SQLITE_MAX_ATTACHED 10
167+ #endif
168+ #ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH
169+ #define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000
170+ #endif
171+ #ifndef SQLITE_MAX_VARIABLE_NUMBER
172+ #define SQLITE_MAX_VARIABLE_NUMBER 32766
173+ #endif
174+ #ifndef SQLITE_MAX_TRIGGER_DEPTH
175+ #define SQLITE_MAX_TRIGGER_DEPTH 1000
176+ #endif
177+
143178struct LimitInfo {
144179 std::string_view js_name;
145180 int sqlite_limit_id;
181+ int max_value;
146182};
147183
148184static constexpr std::array<LimitInfo, 11 > kLimitMapping = {{
149- {" length" , SQLITE_LIMIT_LENGTH},
150- {" sqlLength" , SQLITE_LIMIT_SQL_LENGTH},
151- {" column" , SQLITE_LIMIT_COLUMN},
152- {" exprDepth" , SQLITE_LIMIT_EXPR_DEPTH},
153- {" compoundSelect" , SQLITE_LIMIT_COMPOUND_SELECT},
154- {" vdbeOp" , SQLITE_LIMIT_VDBE_OP},
155- {" functionArg" , SQLITE_LIMIT_FUNCTION_ARG},
156- {" attach" , SQLITE_LIMIT_ATTACHED},
157- {" likePatternLength" , SQLITE_LIMIT_LIKE_PATTERN_LENGTH},
158- {" variableNumber" , SQLITE_LIMIT_VARIABLE_NUMBER},
159- {" triggerDepth" , SQLITE_LIMIT_TRIGGER_DEPTH},
185+ {" length" , SQLITE_LIMIT_LENGTH, SQLITE_MAX_LENGTH},
186+ {" sqlLength" , SQLITE_LIMIT_SQL_LENGTH, SQLITE_MAX_SQL_LENGTH},
187+ {" column" , SQLITE_LIMIT_COLUMN, SQLITE_MAX_COLUMN},
188+ {" exprDepth" , SQLITE_LIMIT_EXPR_DEPTH, SQLITE_MAX_EXPR_DEPTH},
189+ {" compoundSelect" ,
190+ SQLITE_LIMIT_COMPOUND_SELECT,
191+ SQLITE_MAX_COMPOUND_SELECT},
192+ {" vdbeOp" , SQLITE_LIMIT_VDBE_OP, SQLITE_MAX_VDBE_OP},
193+ {" functionArg" , SQLITE_LIMIT_FUNCTION_ARG, SQLITE_MAX_FUNCTION_ARG},
194+ {" attach" , SQLITE_LIMIT_ATTACHED, SQLITE_MAX_ATTACHED},
195+ {" likePatternLength" ,
196+ SQLITE_LIMIT_LIKE_PATTERN_LENGTH,
197+ SQLITE_MAX_LIKE_PATTERN_LENGTH},
198+ {" variableNumber" ,
199+ SQLITE_LIMIT_VARIABLE_NUMBER,
200+ SQLITE_MAX_VARIABLE_NUMBER},
201+ {" triggerDepth" , SQLITE_LIMIT_TRIGGER_DEPTH, SQLITE_MAX_TRIGGER_DEPTH},
160202}};
161203
162204// Helper function to find limit ID from JS property name
163205static constexpr int GetLimitIdFromName (std::string_view name) {
164- for (const auto & [limit_name, id] : kLimitMapping ) {
165- if (name == limit_name) {
166- return id;
206+ for (const auto & info : kLimitMapping ) {
207+ if (name == info.js_name ) {
208+ return info.sqlite_limit_id ;
209+ }
210+ }
211+ return -1 ; // Not found
212+ }
213+
214+ // Helper function to get max value for a limit ID
215+ static constexpr int GetMaxValueForLimitId (int limit_id) {
216+ for (const auto & info : kLimitMapping ) {
217+ if (info.sqlite_limit_id == limit_id) {
218+ return info.max_value ;
167219 }
168220 }
169221 return -1 ; // Not found
@@ -345,7 +397,7 @@ class CustomAggregate {
345397 static inline void xStepBase (sqlite3_context* ctx,
346398 int argc,
347399 sqlite3_value** argv,
348- Global<Function> CustomAggregate::*mptr) {
400+ Global<Function> CustomAggregate::* mptr) {
349401 CustomAggregate* self =
350402 static_cast <CustomAggregate*>(sqlite3_user_data (ctx));
351403 Environment* env = self->env_ ;
@@ -806,6 +858,14 @@ Intercepted DatabaseSyncLimits::LimitsSetter(
806858 return Intercepted::kYes ;
807859 }
808860
861+ // Validate against compile-time maximum
862+ int max_value = GetMaxValueForLimitId (limit_id);
863+ if (new_value > max_value) {
864+ THROW_ERR_OUT_OF_RANGE (isolate,
865+ " Limit value exceeds compile-time maximum." );
866+ return Intercepted::kYes ;
867+ }
868+
809869 sqlite3_limit (limits->database_ ->Connection (), limit_id, new_value);
810870 return Intercepted::kYes ;
811871}
@@ -1340,6 +1400,14 @@ void DatabaseSync::New(const FunctionCallbackInfo<Value>& args) {
13401400 return ;
13411401 }
13421402
1403+ if (limit_val > kLimitMapping [i].max_value ) {
1404+ std::string msg = " The \" options.limits." +
1405+ std::string (kLimitMapping [i].js_name ) +
1406+ " \" argument exceeds compile-time maximum." ;
1407+ THROW_ERR_OUT_OF_RANGE (env->isolate (), msg);
1408+ return ;
1409+ }
1410+
13431411 open_config.set_initial_limit (kLimitMapping [i].sqlite_limit_id ,
13441412 limit_val);
13451413 }
0 commit comments