Skip to content

Commit

Permalink
style: Check that we do not insert more than MAX_GRID_LINE subgrid li…
Browse files Browse the repository at this point in the history
…ne name lists while constructing the list

This helps avoid OOM with very large repeats.

Differential Revision: https://phabricator.services.mozilla.com/D161533
  • Loading branch information
Emily McDonough authored and mrobinson committed Nov 3, 2023
1 parent e520c37 commit 8193fb3
Showing 1 changed file with 23 additions and 12 deletions.
35 changes: 23 additions & 12 deletions components/style/values/generics/grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,11 @@ impl Parse for LineNameList {
input.expect_ident_matching("subgrid")?;
let mut line_names = vec![];
let mut fill_data = None;
// Rather than truncating the result after inserting values, just
// have a maximum number of values. This gives us an early out on very
// large name lists, but more importantly prevents OOM on huge repeat
// expansions. (bug 1583429)
let mut max_remaining = MAX_GRID_LINE as usize;

loop {
let repeat_parse_result = input.try_parse(|input| {
Expand All @@ -685,34 +690,40 @@ impl Parse for LineNameList {
})
});
if let Ok((names_list, count)) = repeat_parse_result {
let mut handle_size = |n| {
let n = cmp::min(n, max_remaining);
max_remaining -= n;
n
};
match count {
// FIXME(emilio): we shouldn't expand repeat() at
// parse time for subgrid. (bug 1583429)
RepeatCount::Number(num) => line_names.extend(
names_list
.iter()
.cloned()
.cycle()
.take(num.value() as usize * names_list.len()),
),
RepeatCount::Number(num) => {
let n = handle_size(
num.value() as usize * names_list.len());
line_names.extend(
names_list.iter().cloned().cycle().take(n));
},
RepeatCount::AutoFill if fill_data.is_none() => {
let fill_idx = line_names.len();
let fill_len = names_list.len();
fill_data = Some((fill_idx, fill_len));
line_names.extend(names_list.into_iter());
let n = handle_size(fill_len);
line_names.extend(names_list.into_iter().take(n));
},
_ => return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
}
} else if let Ok(names) = input.try_parse(parse_line_names) {
line_names.push(names);
if max_remaining > 0 {
line_names.push(names);
max_remaining -= 1;
}
} else {
break;
}
}

if line_names.len() > MAX_GRID_LINE as usize {
line_names.truncate(MAX_GRID_LINE as usize);
}
debug_assert!(line_names.len() <= MAX_GRID_LINE as usize);

let (fill_start, fill_len) = fill_data.unwrap_or((0, 0));

Expand Down

0 comments on commit 8193fb3

Please sign in to comment.