Skip to content

Commit b66ef02

Browse files
committed
Fix non-unicode DB filesystem regression test
1 parent e976252 commit b66ef02

2 files changed

Lines changed: 68 additions & 6 deletions

File tree

src/webserver/http.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -496,12 +496,11 @@ pub async fn main_handler(
496496
Serve(path) => {
497497
let if_modified_since = IfModifiedSince::parse(&service_request).ok();
498498
let app_state: &web::Data<AppState> = service_request.app_data().expect("app_state");
499-
serve_file(
500-
path.as_os_str().to_str().unwrap(),
501-
app_state,
502-
if_modified_since,
503-
)
504-
.await
499+
let path = path
500+
.as_os_str()
501+
.to_str()
502+
.ok_or_else(|| ErrorBadRequest("requested file path must be valid unicode"))?;
503+
serve_file(path, app_state, if_modified_since).await
505504
}
506505
}
507506
.map(|response| service_request.into_response(response))

tests/core/mod.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ use sqlpage::{
44
AppState,
55
};
66
use sqlx::Executor as _;
7+
#[cfg(unix)]
8+
use std::ffi::OsString;
9+
#[cfg(unix)]
10+
use std::os::unix::ffi::OsStringExt;
711

812
use crate::common::{make_app_data_from_config, req_path, req_path_with_app_data, test_config};
913

@@ -87,6 +91,65 @@ async fn test_routing_with_db_fs() {
8791
);
8892
}
8993

94+
#[actix_web::test]
95+
async fn test_non_unicode_static_path_returns_bad_request_with_db_fs() {
96+
let mut config = test_config();
97+
if !config.database_url.starts_with("sqlite") {
98+
return;
99+
}
100+
config.database_url =
101+
"sqlite://file:test_non_unicode_static_path?mode=memory&cache=shared".to_string();
102+
103+
let expected_db_path = {
104+
let decoded = percent_encoding::percent_decode_str("%FF.txt");
105+
#[cfg(unix)]
106+
{
107+
std::path::PathBuf::from(OsString::from_vec(decoded.collect::<Vec<u8>>()))
108+
.display()
109+
.to_string()
110+
}
111+
#[cfg(not(unix))]
112+
{
113+
decoded.decode_utf8_lossy().to_string()
114+
}
115+
};
116+
117+
use sqlx::Connection as _;
118+
let mut conn = sqlx::AnyConnection::connect(&config.database_url)
119+
.await
120+
.unwrap();
121+
conn.execute("DROP TABLE IF EXISTS sqlpage_files")
122+
.await
123+
.unwrap();
124+
conn.execute(sqlpage::filesystem::DbFsQueries::get_create_table_sql(
125+
sqlpage::webserver::database::SupportedDatabase::Sqlite,
126+
))
127+
.await
128+
.unwrap();
129+
sqlx::query("INSERT INTO sqlpage_files(path, contents) VALUES (?, ?)")
130+
.bind(expected_db_path)
131+
.bind("file from db fs".as_bytes())
132+
.execute(&mut conn)
133+
.await
134+
.unwrap();
135+
136+
let state = AppState::init(&config).await.unwrap();
137+
138+
let app_data = actix_web::web::Data::new(state);
139+
let req = test::TestRequest::get()
140+
.uri("/%FF.txt")
141+
.app_data(app_data)
142+
.to_srv_request();
143+
144+
let err = sqlpage::webserver::http::main_handler(req)
145+
.await
146+
.expect_err("non-unicode path should not panic and must return bad request");
147+
assert_eq!(
148+
err.as_response_error().status_code(),
149+
StatusCode::BAD_REQUEST
150+
);
151+
}
152+
90153
#[actix_web::test]
91154
async fn test_routing_with_prefix() {
92155
let mut config = test_config();

0 commit comments

Comments
 (0)