Compare commits

...

3 Commits

Author SHA1 Message Date
Brent Traut
9ba6e83048 Merge origin/main to resolve PR #24670 conflict 2026-05-26 21:07:31 -07:00
Brent Traut
558e6b3a67 Fix Rust 1.94 exec-server lint 2026-05-26 17:50:22 -07:00
Brent Traut
ad306b67dd Upgrade SQLx to ship fixed SQLite 2026-05-26 17:30:54 -07:00
9 changed files with 518 additions and 321 deletions

101
MODULE.bazel.lock generated

File diff suppressed because one or more lines are too long

673
codex-rs/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -366,13 +366,14 @@ sha2 = "0.10"
shlex = "1.3.0"
similar = "2.7.0"
socket2 = "0.6.1"
sqlx = { version = "0.8.6", default-features = false, features = [
sqlx = { version = "0.9.0", default-features = false, features = [
"chrono",
"json",
"macros",
"migrate",
"runtime-tokio-rustls",
"sqlite",
"runtime-tokio",
"sqlite-bundled",
"tls-rustls-ring",
"time",
"uuid",
] }

View File

@@ -218,7 +218,7 @@ impl LazyRemoteExecServerClient {
}
let next_client = match self.cached_client() {
Some(_client)
Some(_)
if matches!(
&self.transport_params,
ExecServerTransportParams::WebSocketUrl { .. }

View File

@@ -19,6 +19,8 @@ fn runtime_migrator(base: &'static Migrator) -> Migrator {
ignore_missing: true,
locking: base.locking,
no_tx: base.no_tx,
table_name: base.table_name.clone(),
create_schemas: base.create_schemas.clone(),
}
}

View File

@@ -569,6 +569,36 @@ mod tests {
let _ = tokio::fs::remove_dir_all(codex_home).await;
}
#[tokio::test]
async fn linked_sqlite_has_wal_reset_bug_fix() {
let pool = SqlitePool::connect("sqlite::memory:")
.await
.expect("open in-memory sqlite db");
let sqlite_version: String = sqlx::query_scalar("SELECT sqlite_version()")
.fetch_one(&pool)
.await
.expect("query linked sqlite version");
pool.close().await;
let version = sqlite_version
.split('.')
.map(|part| part.parse::<u32>().expect("numeric sqlite version"))
.collect::<Vec<_>>();
assert_eq!(
version.len(),
3,
"unexpected SQLite version: {sqlite_version}"
);
let version = (version[0], version[1], version[2]);
let includes_wal_reset_fix = version >= (3, 51, 3)
|| (version.0 == 3 && version.1 == 50 && version.2 >= 7)
|| (version.0 == 3 && version.1 == 44 && version.2 >= 6);
assert!(
includes_wal_reset_fix,
"linked SQLite {sqlite_version} is vulnerable to the WAL-reset corruption bug"
);
}
#[tokio::test]
async fn open_state_sqlite_tolerates_newer_applied_migrations() {
let codex_home = unique_temp_dir();

View File

@@ -450,7 +450,7 @@ RETURNING
"#,
);
let mut query = sqlx::query(&query)
let mut query = sqlx::query(sqlx::AssertSqlSafe(query))
.bind(time_delta_seconds)
.bind(token_delta)
.bind(token_delta)

View File

@@ -392,7 +392,7 @@ WHERE cumulative_estimated_bytes <= ?
ORDER BY ts DESC, ts_nanos DESC, id DESC
"#
);
let mut sql = sqlx::query_as::<_, FeedbackLogRow>(query.as_str());
let mut sql = sqlx::query_as::<_, FeedbackLogRow>(sqlx::AssertSqlSafe(query));
for thread_id in thread_ids {
sql = sql.bind(thread_id);
}
@@ -463,7 +463,7 @@ fn format_feedback_log_line(
line
}
fn push_log_filters<'a>(builder: &mut QueryBuilder<'a, Sqlite>, query: &'a LogQuery) {
fn push_log_filters(builder: &mut QueryBuilder<Sqlite>, query: &LogQuery) {
if !query.levels_upper.is_empty() {
builder.push(" AND UPPER(level) IN (");
{
@@ -511,11 +511,7 @@ fn push_log_filters<'a>(builder: &mut QueryBuilder<'a, Sqlite>, query: &'a LogQu
}
}
fn push_like_filters<'a>(
builder: &mut QueryBuilder<'a, Sqlite>,
column: &str,
filters: &'a [String],
) {
fn push_like_filters(builder: &mut QueryBuilder<Sqlite>, column: &str, filters: &[String]) {
if filters.is_empty() {
return;
}
@@ -613,6 +609,8 @@ mod tests {
ignore_missing: false,
locking: true,
no_tx: false,
table_name: Cow::Borrowed("_sqlx_migrations"),
create_schemas: Cow::Borrowed(&[]),
};
let pool = SqlitePool::connect_with(
SqliteConnectOptions::new()

View File

@@ -260,7 +260,7 @@ LIMIT 2
}
query.push_str(" ORDER BY child_thread_id");
let mut sql = sqlx::query(query.as_str()).bind(parent_thread_id.to_string());
let mut sql = sqlx::query(sqlx::AssertSqlSafe(query)).bind(parent_thread_id.to_string());
if let Some(status) = status {
sql = sql.bind(status.to_string());
}
@@ -301,7 +301,7 @@ ORDER BY depth ASC, child_thread_id ASC
"#
);
let mut sql = sqlx::query(query.as_str()).bind(root_thread_id.to_string());
let mut sql = sqlx::query(sqlx::AssertSqlSafe(query)).bind(root_thread_id.to_string());
if let Some(status) = status {
let status = status.to_string();
sql = sql.bind(status.clone()).bind(status);
@@ -999,7 +999,7 @@ fn one_thread_id_from_rows(
}
}
pub(super) fn push_thread_select_columns(builder: &mut QueryBuilder<'_, Sqlite>) {
pub(super) fn push_thread_select_columns(builder: &mut QueryBuilder<Sqlite>) {
builder.push(
r#"
SELECT
@@ -1076,7 +1076,7 @@ pub struct ThreadFilterOptions<'a> {
}
pub(super) fn push_thread_filters<'a>(
builder: &mut QueryBuilder<'a, Sqlite>,
builder: &mut QueryBuilder<Sqlite>,
options: ThreadFilterOptions<'a>,
) {
let ThreadFilterOptions {
@@ -1156,7 +1156,7 @@ pub(super) fn push_thread_filters<'a>(
}
pub(super) fn push_thread_order_and_limit(
builder: &mut QueryBuilder<'_, Sqlite>,
builder: &mut QueryBuilder<Sqlite>,
sort_key: SortKey,
sort_direction: SortDirection,
limit: usize,