mirror of
https://github.com/edera-dev/sprout.git
synced 2025-12-19 15:50:18 +00:00
fix(context): add context finalization iteration limit
This prevents any possibility of an infinite loop during finalization.
This commit is contained in:
@@ -1,11 +1,14 @@
|
||||
use crate::actions::ActionDeclaration;
|
||||
use crate::options::SproutOptions;
|
||||
use anyhow::Result;
|
||||
use anyhow::anyhow;
|
||||
use anyhow::{Result, bail};
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::rc::Rc;
|
||||
use uefi::proto::device_path::DevicePath;
|
||||
|
||||
/// The maximum number of iterations that can be performed in [SproutContext::finalize].
|
||||
const CONTEXT_FINALIZE_ITERATION_LIMIT: usize = 100;
|
||||
|
||||
/// Declares a root context for Sprout.
|
||||
/// This contains data that needs to be shared across Sprout.
|
||||
#[derive(Default)]
|
||||
@@ -151,11 +154,20 @@ impl SproutContext {
|
||||
/// Finalizes a context by producing a context with no parent that contains all the values
|
||||
/// of all parent contexts merged. This makes it possible to ensure [SproutContext] has no
|
||||
/// inheritance with other [SproutContext]s. It will still contain a [RootContext] however.
|
||||
pub fn finalize(&self) -> SproutContext {
|
||||
pub fn finalize(&self) -> Result<SproutContext> {
|
||||
// Collect all the values from the context and its parents.
|
||||
let mut current_values = self.all_values();
|
||||
|
||||
// To ensure that there is no possible infinite loop, we need to check
|
||||
// the number of iterations. If it exceeds 100, we bail.
|
||||
let mut iterations: usize = 0;
|
||||
loop {
|
||||
iterations += 1;
|
||||
|
||||
if iterations > CONTEXT_FINALIZE_ITERATION_LIMIT {
|
||||
bail!("infinite loop detected in context finalization");
|
||||
}
|
||||
|
||||
let mut did_change = false;
|
||||
let mut values = BTreeMap::new();
|
||||
for (key, value) in ¤t_values {
|
||||
@@ -176,11 +188,11 @@ impl SproutContext {
|
||||
}
|
||||
|
||||
// Produce the final context.
|
||||
Self {
|
||||
Ok(Self {
|
||||
root: self.root.clone(),
|
||||
parent: None,
|
||||
values: current_values,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Stamps the `text` value with the specified `values` map. The returned value indicates
|
||||
|
||||
Reference in New Issue
Block a user