mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
style: Check that we do not insert more than MAX_GRID_LINE subgrid line name lists while constructing the list
This helps avoid OOM with very large repeats. Differential Revision: https://phabricator.services.mozilla.com/D161533
This commit is contained in:
parent
e520c3796d
commit
8193fb3985
1 changed files with 23 additions and 12 deletions
|
@ -669,6 +669,11 @@ impl Parse for LineNameList {
|
||||||
input.expect_ident_matching("subgrid")?;
|
input.expect_ident_matching("subgrid")?;
|
||||||
let mut line_names = vec![];
|
let mut line_names = vec![];
|
||||||
let mut fill_data = None;
|
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 {
|
loop {
|
||||||
let repeat_parse_result = input.try_parse(|input| {
|
let repeat_parse_result = input.try_parse(|input| {
|
||||||
|
@ -685,34 +690,40 @@ impl Parse for LineNameList {
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
if let Ok((names_list, count)) = repeat_parse_result {
|
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 {
|
match count {
|
||||||
// FIXME(emilio): we shouldn't expand repeat() at
|
// FIXME(emilio): we shouldn't expand repeat() at
|
||||||
// parse time for subgrid. (bug 1583429)
|
// parse time for subgrid. (bug 1583429)
|
||||||
RepeatCount::Number(num) => line_names.extend(
|
RepeatCount::Number(num) => {
|
||||||
names_list
|
let n = handle_size(
|
||||||
.iter()
|
num.value() as usize * names_list.len());
|
||||||
.cloned()
|
line_names.extend(
|
||||||
.cycle()
|
names_list.iter().cloned().cycle().take(n));
|
||||||
.take(num.value() as usize * names_list.len()),
|
},
|
||||||
),
|
|
||||||
RepeatCount::AutoFill if fill_data.is_none() => {
|
RepeatCount::AutoFill if fill_data.is_none() => {
|
||||||
let fill_idx = line_names.len();
|
let fill_idx = line_names.len();
|
||||||
let fill_len = names_list.len();
|
let fill_len = names_list.len();
|
||||||
fill_data = Some((fill_idx, fill_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)),
|
_ => return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
|
||||||
}
|
}
|
||||||
} else if let Ok(names) = input.try_parse(parse_line_names) {
|
} 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 {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if line_names.len() > MAX_GRID_LINE as usize {
|
debug_assert!(line_names.len() <= MAX_GRID_LINE as usize);
|
||||||
line_names.truncate(MAX_GRID_LINE as usize);
|
|
||||||
}
|
|
||||||
|
|
||||||
let (fill_start, fill_len) = fill_data.unwrap_or((0, 0));
|
let (fill_start, fill_len) = fill_data.unwrap_or((0, 0));
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue