0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-02-01 12:16:11 -05:00

fix(ext/node): throw RangeError when sqlite INTEGER is too large (#27907)

Signed-off-by: Divy Srivastava <dj.srivastava23@gmail.com>
This commit is contained in:
Divy Srivastava 2025-02-01 13:19:53 +05:30 committed by GitHub
parent 9da6a20e57
commit 7d19668255
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 23 additions and 5 deletions

View file

@ -38,4 +38,7 @@ pub enum SqliteError {
#[class(generic)]
#[error("Invalid constructor")]
InvalidConstructor,
#[class(range)]
#[error("The value of column {0} is too large to be represented as a JavaScript number: {1}")]
NumberTooLarge(i32, i64),
}

View file

@ -12,6 +12,9 @@ use serde::Serialize;
use super::SqliteError;
// ECMA-262, 15th edition, 21.1.2.6. Number.MAX_SAFE_INTEGER (2^53-1)
const MAX_SAFE_JS_INTEGER: i64 = 9007199254740991;
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RunStatementResult {
@ -122,17 +125,19 @@ impl StatementSync {
&self,
index: i32,
scope: &mut v8::HandleScope<'a>,
) -> v8::Local<'a, v8::Value> {
) -> Result<v8::Local<'a, v8::Value>, SqliteError> {
// SAFETY: `self.inner` is a valid pointer to a sqlite3_stmt
// as it lives as long as the StatementSync instance.
unsafe {
match ffi::sqlite3_column_type(self.inner, index) {
Ok(match ffi::sqlite3_column_type(self.inner, index) {
ffi::SQLITE_INTEGER => {
let value = ffi::sqlite3_column_int64(self.inner, index);
if self.use_big_ints.get() {
v8::BigInt::new_from_i64(scope, value).into()
} else {
} else if value.abs() <= MAX_SAFE_JS_INTEGER {
v8::Integer::new(scope, value as _).into()
} else {
return Err(SqliteError::NumberTooLarge(index, value));
}
}
ffi::SQLITE_FLOAT => {
@ -162,7 +167,7 @@ impl StatementSync {
}
ffi::SQLITE_NULL => v8::null(scope).into(),
_ => v8::undefined(scope).into(),
}
})
}
}
@ -183,7 +188,7 @@ impl StatementSync {
let mut values = Vec::with_capacity(num_cols);
for (index, name) in iter {
let value = self.column_value(index, scope);
let value = self.column_value(index, scope)?;
let name =
v8::String::new_from_utf8(scope, name, v8::NewStringType::Normal)
.unwrap()

View file

@ -73,6 +73,16 @@ Deno.test("[node/sqlite] StatementSync read bigints are supported", () => {
assertEquals(stmt.get(), { key: 1n, __proto__: null });
});
Deno.test("[node/sqlite] StatementSync integer too large", () => {
const db = new DatabaseSync(":memory:");
db.exec("CREATE TABLE data(key INTEGER PRIMARY KEY);");
db.prepare("INSERT INTO data (key) VALUES (?)").run(
Number.MAX_SAFE_INTEGER + 1,
);
assertThrows(() => db.prepare("SELECT * FROM data").get());
});
Deno.test("[node/sqlite] StatementSync blob are Uint8Array", () => {
const db = new DatabaseSync(":memory:");
const obj = db.prepare("select cast('test' as blob)").all();