mirror of
https://github.com/RGBCube/serenity
synced 2025-07-10 04:17:34 +00:00
Shell: Store LocalFrames as NonnullOwnPtr<LocalFrame> instead
As Vector<T> will relocate objects to resize, we cannot assume that the address of a specific LocalFrame will stay constant, or that the reference will not be dangling to begin with. Fixes an assertion that fires when a frame push causes the Vector to reallocate.
This commit is contained in:
parent
a7f4f6afc3
commit
bedad383b5
3 changed files with 28 additions and 12 deletions
|
@ -1033,7 +1033,7 @@ RefPtr<Value> ForLoop::run(RefPtr<Shell> shell)
|
||||||
RefPtr<Value> block_value;
|
RefPtr<Value> block_value;
|
||||||
|
|
||||||
{
|
{
|
||||||
auto frame = shell->push_frame();
|
auto frame = shell->push_frame(String::formatted("for ({})", this));
|
||||||
shell->set_local_variable(m_variable_name, value);
|
shell->set_local_variable(m_variable_name, value);
|
||||||
|
|
||||||
block_value = m_block->run(shell);
|
block_value = m_block->run(shell);
|
||||||
|
@ -1585,7 +1585,7 @@ RefPtr<Value> MatchExpr::run(RefPtr<Shell> shell)
|
||||||
return pattern;
|
return pattern;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto frame = shell->push_frame();
|
auto frame = shell->push_frame(String::formatted("match ({})", this));
|
||||||
if (!m_expr_name.is_empty())
|
if (!m_expr_name.is_empty())
|
||||||
shell->set_local_variable(m_expr_name, value);
|
shell->set_local_variable(m_expr_name, value);
|
||||||
|
|
||||||
|
|
|
@ -463,7 +463,7 @@ bool Shell::invoke_function(const AST::Command& command, int& retval)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto frame = push_frame();
|
auto frame = push_frame(String::formatted("function {}", function.name));
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
for (auto& arg : function.arguments) {
|
for (auto& arg : function.arguments) {
|
||||||
++index;
|
++index;
|
||||||
|
@ -489,9 +489,12 @@ String Shell::format(const StringView& source, ssize_t& cursor) const
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Shell::Frame Shell::push_frame()
|
Shell::Frame Shell::push_frame(String name)
|
||||||
{
|
{
|
||||||
m_local_frames.empend();
|
m_local_frames.append(make<LocalFrame>(name, decltype(LocalFrame::local_variables) {}));
|
||||||
|
#ifdef SH_DEBUG
|
||||||
|
dbg() << "New frame '" << name << "' at " << &m_local_frames.last();
|
||||||
|
#endif
|
||||||
return { m_local_frames, m_local_frames.last() };
|
return { m_local_frames, m_local_frames.last() };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,7 +508,12 @@ Shell::Frame::~Frame()
|
||||||
{
|
{
|
||||||
if (!should_destroy_frame)
|
if (!should_destroy_frame)
|
||||||
return;
|
return;
|
||||||
ASSERT(&frames.last() == &frame);
|
if (&frames.last() != &frame) {
|
||||||
|
dbg() << "Frame destruction order violation near " << &frame << " (container = " << this << ") '" << frame.name << "'; current frames:";
|
||||||
|
for (auto& frame : frames)
|
||||||
|
dbg() << "- " << &frame << ": " << frame.name;
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
frames.take_last();
|
frames.take_last();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1504,7 +1512,7 @@ void Shell::notify_child_event()
|
||||||
Shell::Shell()
|
Shell::Shell()
|
||||||
: m_default_constructed(true)
|
: m_default_constructed(true)
|
||||||
{
|
{
|
||||||
push_frame().leak_frame();
|
push_frame("main").leak_frame();
|
||||||
|
|
||||||
int rc = gethostname(hostname, Shell::HostNameSize);
|
int rc = gethostname(hostname, Shell::HostNameSize);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
|
@ -1544,7 +1552,7 @@ Shell::Shell(Line::Editor& editor)
|
||||||
tcsetpgrp(0, getpgrp());
|
tcsetpgrp(0, getpgrp());
|
||||||
m_pid = getpid();
|
m_pid = getpid();
|
||||||
|
|
||||||
push_frame().leak_frame();
|
push_frame("main").leak_frame();
|
||||||
|
|
||||||
int rc = gethostname(hostname, Shell::HostNameSize);
|
int rc = gethostname(hostname, Shell::HostNameSize);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "Parser.h"
|
#include "Parser.h"
|
||||||
#include <AK/CircularQueue.h>
|
#include <AK/CircularQueue.h>
|
||||||
#include <AK/HashMap.h>
|
#include <AK/HashMap.h>
|
||||||
|
#include <AK/NonnullOwnPtrVector.h>
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
#include <AK/StringBuilder.h>
|
#include <AK/StringBuilder.h>
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
|
@ -114,11 +115,18 @@ public:
|
||||||
RefPtr<Line::Editor> editor() const { return m_editor; }
|
RefPtr<Line::Editor> editor() const { return m_editor; }
|
||||||
|
|
||||||
struct LocalFrame {
|
struct LocalFrame {
|
||||||
|
LocalFrame(const String& name, HashMap<String, RefPtr<AST::Value>> variables)
|
||||||
|
: name(name)
|
||||||
|
, local_variables(move(variables))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
String name;
|
||||||
HashMap<String, RefPtr<AST::Value>> local_variables;
|
HashMap<String, RefPtr<AST::Value>> local_variables;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Frame {
|
struct Frame {
|
||||||
Frame(Vector<LocalFrame>& frames, const LocalFrame& frame)
|
Frame(NonnullOwnPtrVector<LocalFrame>& frames, const LocalFrame& frame)
|
||||||
: frames(frames)
|
: frames(frames)
|
||||||
, frame(frame)
|
, frame(frame)
|
||||||
{
|
{
|
||||||
|
@ -128,12 +136,12 @@ public:
|
||||||
void leak_frame() { should_destroy_frame = false; }
|
void leak_frame() { should_destroy_frame = false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector<LocalFrame>& frames;
|
NonnullOwnPtrVector<LocalFrame>& frames;
|
||||||
const LocalFrame& frame;
|
const LocalFrame& frame;
|
||||||
bool should_destroy_frame { true };
|
bool should_destroy_frame { true };
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] Frame push_frame();
|
[[nodiscard]] Frame push_frame(String name);
|
||||||
void pop_frame();
|
void pop_frame();
|
||||||
|
|
||||||
static String escape_token(const String& token);
|
static String escape_token(const String& token);
|
||||||
|
@ -247,7 +255,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
HashMap<String, ShellFunction> m_functions;
|
HashMap<String, ShellFunction> m_functions;
|
||||||
Vector<LocalFrame> m_local_frames;
|
NonnullOwnPtrVector<LocalFrame> m_local_frames;
|
||||||
NonnullRefPtrVector<AST::Redirection> m_global_redirections;
|
NonnullRefPtrVector<AST::Redirection> m_global_redirections;
|
||||||
|
|
||||||
HashMap<String, String> m_aliases;
|
HashMap<String, String> m_aliases;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue