forked from 1b-agent/opencadstudio-upstream
fix(plot-style): bound custom lineweight table keys to u8 range
Bug: Custom lineweight table entries in a CTB are keyed by a number parsed from the file and stored without an upper bound, but the only reader (resolve_lineweight) indexes through entry.lineweight: u8. A key beyond u8::MAX (e.g. 18446744073709551615 in a crafted file) caused an out-of-bounds-style failure or a multi-GB table allocation when the style was applied. Reproduce: 1. Craft a CTB whose custom lineweight table uses a huge key (usize::MAX). 2. Apply the style or open plot settings. 3. Before: overflow panic (or a giant allocation). 4. After: the key is out of range, the line is ignored like any other malformed CTB line, and the style loads. Fix: Keys are bounded to u8::MAX when parsed - exactly the range the u8-typed reader can ever use. In-range keys behave as before; keys 256 and above are dropped. Tests: a usize::MAX key does not overflow, an in-range key is kept and applied, 256 is ignored.
This commit is contained in:
1 parent
ac6aa750f6
commit
790da218b5
1 file changed
+42
-3
+42
-3
@@ -785,11 +785,19 @@ fn parse_plot_style_text(text: &str, name: String, is_stb: bool) -> Result<PlotS
|
||||
_ => {}
|
||||
},
|
||||
Section::Lineweights => {
|
||||
// The key is file-controlled: `18446744073709551615` made
|
||||
// `index + 1` overflow (debug panic, release wrap to
|
||||
// `resize(0)` then OOB), and `500000000` resized a 2 GB
|
||||
// table. Entries past 255 are unreachable — the consumer
|
||||
// indexes with `PlotStyleEntry.lineweight: u8` — so
|
||||
// oversized keys are ignored like other malformed lines.
|
||||
if let (Ok(index), Ok(weight)) = (key.parse::<usize>(), value.parse::<f32>()) {
|
||||
if lineweights.len() <= index {
|
||||
lineweights.resize(index + 1, 0.0);
|
||||
if index <= u8::MAX as usize {
|
||||
if lineweights.len() <= index {
|
||||
lineweights.resize(index + 1, 0.0);
|
||||
}
|
||||
lineweights[index] = weight;
|
||||
}
|
||||
lineweights[index] = weight;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
@@ -1088,3 +1096,34 @@ mod inflate_limit_tests {
|
||||
assert!(error.contains("limit"), "{error}");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod lineweight_table_tests {
|
||||
use super::{parse_plot_style_text, LW_TABLE};
|
||||
|
||||
fn parse(text: &str) -> super::PlotStyleTable {
|
||||
parse_plot_style_text(text, "crafted.ctb".into(), false).expect("parses")
|
||||
}
|
||||
|
||||
/// The table key is file-controlled: `18446744073709551615` made
|
||||
/// `index + 1` overflow — debug builds panic, release wraps to
|
||||
/// `resize(0)` and then panics OOB at `lineweights[usize::MAX]` — and
|
||||
/// `500000000` resized a 2 GB table (allocation abort). Entries past
|
||||
/// 255 are unreachable anyway: `PlotStyleEntry.lineweight` is a `u8`.
|
||||
#[test]
|
||||
fn oversized_lineweight_table_keys_are_ignored() {
|
||||
let table = parse("custom_lineweight_table{\n18446744073709551615=0.5\n}\n");
|
||||
assert_eq!(table.lineweights, LW_TABLE.to_vec());
|
||||
}
|
||||
|
||||
/// In-range keys still extend the table; 256 (beyond `u8`) is ignored.
|
||||
#[test]
|
||||
fn in_range_lineweight_table_keys_are_kept() {
|
||||
let table = parse("custom_lineweight_table{\n30=0.7\n}\n");
|
||||
assert_eq!(table.lineweights.len(), 31);
|
||||
assert_eq!(table.lineweights[30], 0.7);
|
||||
|
||||
let table = parse("custom_lineweight_table{\n256=0.7\n}\n");
|
||||
assert_eq!(table.lineweights, LW_TABLE.to_vec());
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user