Skip to content

Commit 346d53c

Browse files
committed
added max value control
1 parent 2df2557 commit 346d53c

File tree

2 files changed

+102
-15
lines changed

2 files changed

+102
-15
lines changed

src/node_sqlite.cc

Lines changed: 83 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
143178
struct LimitInfo {
144179
std::string_view js_name;
145180
int sqlite_limit_id;
181+
int max_value;
146182
};
147183

148184
static 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
163205
static 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
}

test/parallel/test-sqlite-limits.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,25 @@ suite('DatabaseSync limits', () => {
158158
});
159159
});
160160

161+
test('throws on value exceeding compile-time maximum via setter', (t) => {
162+
const db = new DatabaseSync(':memory:');
163+
t.assert.throws(() => {
164+
db.limits.attach = 100;
165+
}, {
166+
name: 'RangeError',
167+
message: /Limit value exceeds compile-time maximum/,
168+
});
169+
});
170+
171+
test('throws on value exceeding compile-time maximum in constructor', (t) => {
172+
t.assert.throws(() => {
173+
new DatabaseSync(':memory:', { limits: { attach: 100 } });
174+
}, {
175+
name: 'RangeError',
176+
message: /options\.limits\.attach.*exceeds compile-time maximum/,
177+
});
178+
});
179+
161180
test('partial limits in constructor', (t) => {
162181
const db = new DatabaseSync(':memory:', {
163182
limits: {

0 commit comments

Comments
 (0)