address review: stop collecting JSON keys at the column limit and reject oversized row counts before building rows

This commit is contained in:
Dylan M. Taylor
2026-11-03 23:57:00 +00:00
parent 052ee60218
commit 31bea74bd3
2 changed files with 20 additions and 3 deletions
+8 -3
View File
@@ -70,14 +70,19 @@ pub(super) fn from_csv(s: &mut Session, p: &Json) -> Result<Json> {
for o in &arr {
if let Some(m) = o.as_object() {
for k in m.keys() {
if seen.insert(k.as_str()) {
if !seen.contains(k.as_str()) {
// Stop collecting at the column limit.
if keys.len() >= gridcraft_core::MAX_COLS as usize {
return Err(EngineError::Other("The data has more fields than a sheet has columns.".into()));
}
seen.insert(k.as_str());
keys.push(k.clone());
}
}
}
}
if keys.len() > gridcraft_core::MAX_COLS as usize {
return Err(EngineError::Other("The data has more fields than a sheet has columns.".into()));
if arr.len() as u64 + 1 > u64::from(gridcraft_core::MAX_ROWS) {
return Err(EngineError::Other("The data has more rows than a sheet has.".into()));
}
if (arr.len() as u64 + 1).saturating_mul(keys.len().max(1) as u64) > MAX_IMPORT_CELLS {
return Err(too_many_cells());
+12
View File
@@ -1312,6 +1312,18 @@ fn scripts_leave_file_access_working_after_they_run() {
let _ = std::fs::remove_dir_all(&dir);
}
#[test]
fn get_data_refuses_json_with_too_many_fields_or_rows_before_building_rows() {
let mut s = s();
let wide = format!("[{}]", (0..=gridcraft_core::MAX_COLS).map(|i| format!("{{\"k{i}\":1}}")).collect::<Vec<_>>().join(","));
let err = s.execute("data.fromTextCsv", json!({"text": wide})).unwrap_err().to_string();
assert!(err.contains("more fields"), "{err}");
// MAX_ROWS objects plus the header row are one too many.
let tall = format!("[{}]", vec!["{}"; gridcraft_core::MAX_ROWS as usize].join(","));
let err = s.execute("data.fromTextCsv", json!({"text": tall})).unwrap_err().to_string();
assert!(err.contains("more rows"), "{err}");
}
#[test]
fn scripts_cannot_reach_outside_the_workbook_even_when_trusted() {
let dir = std::env::temp_dir().join(format!("gridcraft-script-deny-{}", std::process::id()));