mirror of
https://github.com/fish-shell/fish-shell.git
synced 2025-01-22 15:52:00 +08:00
Enforce that nobody can push/pop from the global environment stack
This is just a precaution.
This commit is contained in:
parent
7fcbe5b8ab
commit
9ad875cdb7
9
src/env/environment.rs
vendored
9
src/env/environment.rs
vendored
|
@ -173,12 +173,14 @@ impl EnvScoped {
|
||||||
/// This backs the parser's "vars".
|
/// This backs the parser's "vars".
|
||||||
pub struct EnvStack {
|
pub struct EnvStack {
|
||||||
inner: EnvMutex<EnvStackImpl>,
|
inner: EnvMutex<EnvStackImpl>,
|
||||||
|
can_push_pop: bool, // If false, panic on push/pop. Used for the global stack.
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EnvStack {
|
impl EnvStack {
|
||||||
pub fn new() -> EnvStack {
|
pub fn new() -> EnvStack {
|
||||||
EnvStack {
|
EnvStack {
|
||||||
inner: EnvStackImpl::new(),
|
inner: EnvStackImpl::new(),
|
||||||
|
can_push_pop: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,6 +293,7 @@ impl EnvStack {
|
||||||
|
|
||||||
/// Push the variable stack. Used for implementing local variables for functions and for-loops.
|
/// Push the variable stack. Used for implementing local variables for functions and for-loops.
|
||||||
pub fn push(&self, new_scope: bool) {
|
pub fn push(&self, new_scope: bool) {
|
||||||
|
assert!(self.can_push_pop, "push/pop not allowed on global stack");
|
||||||
let mut imp = self.lock();
|
let mut imp = self.lock();
|
||||||
if new_scope {
|
if new_scope {
|
||||||
imp.push_shadowing();
|
imp.push_shadowing();
|
||||||
|
@ -301,6 +304,7 @@ impl EnvStack {
|
||||||
|
|
||||||
/// Pop the variable stack. Used for implementing local variables for functions and for-loops.
|
/// Pop the variable stack. Used for implementing local variables for functions and for-loops.
|
||||||
pub fn pop(&self) {
|
pub fn pop(&self) {
|
||||||
|
assert!(self.can_push_pop, "push/pop not allowed on global stack");
|
||||||
let popped = self.lock().pop();
|
let popped = self.lock().pop();
|
||||||
// Only dispatch variable changes if we are the principal environment.
|
// Only dispatch variable changes if we are the principal environment.
|
||||||
if self.is_principal() {
|
if self.is_principal() {
|
||||||
|
@ -363,7 +367,10 @@ impl EnvStack {
|
||||||
pub fn globals() -> &'static EnvStack {
|
pub fn globals() -> &'static EnvStack {
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
static GLOBALS: OnceLock<EnvStack> = OnceLock::new();
|
static GLOBALS: OnceLock<EnvStack> = OnceLock::new();
|
||||||
GLOBALS.get_or_init(EnvStack::new)
|
GLOBALS.get_or_init(|| EnvStack {
|
||||||
|
inner: EnvStackImpl::new(),
|
||||||
|
can_push_pop: false,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Access the principal variable stack, associated with the principal parser.
|
/// Access the principal variable stack, associated with the principal parser.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::env::{EnvMode, EnvVar, EnvVarFlags, Environment};
|
use crate::env::{EnvMode, EnvStack, EnvVar, EnvVarFlags, Environment};
|
||||||
use crate::parser::Parser;
|
use crate::parser::Parser;
|
||||||
use crate::tests::prelude::*;
|
use crate::tests::prelude::*;
|
||||||
use crate::wchar::prelude::*;
|
use crate::wchar::prelude::*;
|
||||||
|
@ -177,3 +177,16 @@ fn test_env_snapshot() {
|
||||||
vars.pop();
|
vars.pop();
|
||||||
popd();
|
popd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Can't push/pop from globals.
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_no_global_push() {
|
||||||
|
EnvStack::globals().push(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_no_global_pop() {
|
||||||
|
EnvStack::globals().pop();
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user