mirror of
https://github.com/edera-dev/sprout.git
synced 2026-11-04 16:42:20 +00:00
fix(main): skip entries whose context can't be finalized
A value that refers to itself, such as a BLS entry with "options $options", never stops changing when the context is finalized. After the iteration limit, finalizing failed and every entry was lost, although the BLS generator already skips broken entries. Skip just that entry with a warning. A value that refers to itself twice doubles in length every iteration, so it could use up all memory before the limit was reached. Fail once a value grows past 64 KiB.
This commit is contained in:
1 parent
aed9903180
commit
cd38f0271d
2 files changed
+26
-6
No files matched your search
@@ -14,6 +14,11 @@ 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;
|
||||
|
||||
/// The maximum length of a value produced by [SproutContext::finalize].
|
||||
/// A value that refers to itself more than once doubles in length on every iteration,
|
||||
/// so this stops it from using up all memory before the iteration limit is reached.
|
||||
const CONTEXT_FINALIZE_VALUE_LENGTH_LIMIT: usize = 64 * 1024;
|
||||
|
||||
/// Declares a root context for Sprout.
|
||||
/// This contains data that needs to be shared across Sprout.
|
||||
pub struct RootContext {
|
||||
@@ -201,6 +206,10 @@ impl SproutContext {
|
||||
// If the value changed, we need to re-stamp it.
|
||||
did_change = true;
|
||||
}
|
||||
// Ensure the value has not grown without bound.
|
||||
if result.len() > CONTEXT_FINALIZE_VALUE_LENGTH_LIMIT {
|
||||
bail!("value {} is too long while finalizing context", key);
|
||||
}
|
||||
// Insert the new value into the value map.
|
||||
values.insert(key.clone(), result);
|
||||
}
|
||||
|
||||
+17
-6
@@ -260,15 +260,24 @@ fn run() -> Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
for entry in &mut entries {
|
||||
// Entries whose context can't be finalized are skipped, as one broken entry
|
||||
// should not prevent booting any of the other entries.
|
||||
entries.retain_mut(|entry| {
|
||||
let mut context = entry.context().fork();
|
||||
// Insert the values from the entry configuration into the
|
||||
// sprout context to use with the entry itself.
|
||||
context.insert(&entry.declaration().values);
|
||||
let context = context
|
||||
.finalize()
|
||||
.context("unable to finalize context")?
|
||||
.freeze();
|
||||
let context = match context.finalize() {
|
||||
Ok(context) => context.freeze(),
|
||||
Err(error) => {
|
||||
warn!(
|
||||
"skipping entry {}, unable to finalize context: {:#}",
|
||||
entry.name(),
|
||||
error
|
||||
);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
// Provide the new context to the bootable entry.
|
||||
entry.swap_context(context);
|
||||
// Restamp the title and sort key with any values.
|
||||
@@ -282,7 +291,9 @@ fn run() -> Result<()> {
|
||||
entry.mark_default();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
});
|
||||
|
||||
// Sort the entries by their sort key, finalizing the order to show entries. This happens
|
||||
// in reverse order so that entries that would come last show up first in the menu.
|
||||
|
||||
Reference in new issue
Block a user