From f26979a69f8ec00309a07b577db345c6bd9f2d3e Mon Sep 17 00:00:00 2001 From: Daniel Kolesa Date: Wed, 20 Apr 2022 04:31:24 +0200 Subject: [PATCH] protect ident lookups These are global and may be accessed from different states, so they need to be protected. Everything else generally lives locally or is initialized upon startup. --- src/cs_state.cc | 47 +++++++++++++++++++++++++++++++++++++---------- src/cs_state.hh | 7 +++++++ src/cs_vm.cc | 24 ++++++++++++------------ 3 files changed, 56 insertions(+), 22 deletions(-) diff --git a/src/cs_state.cc b/src/cs_state.cc index 1782eaf..02a8cae 100644 --- a/src/cs_state.cc +++ b/src/cs_state.cc @@ -44,15 +44,41 @@ static void *default_alloc(void *, void *p, size_t, size_t ns) { return std::realloc(p, ns); } +ident *internal_state::lookup_ident(std::size_t idx) { + std::lock_guard l{ident_mtx}; + return identmap[idx]; +} + +ident const *internal_state::lookup_ident(std::size_t idx) const { + std::lock_guard l{ident_mtx}; + return identmap[idx]; +} + +std::size_t internal_state::get_identnum() const { + std::lock_guard l{ident_mtx}; + return identmap.size(); +} + +void internal_state::foreach_ident(void (*f)(ident *, void *), void *data) { + auto nids = get_identnum(); + for (std::size_t i = 0; i < nids; ++i) { + std::lock_guard l{ident_mtx}; + f(identmap[i], data); + } +} + ident *internal_state::add_ident(ident *id, ident_impl *impl) { if (!id) { return nullptr; } ident_p{*id}.impl(impl); - idents[id->name()] = id; - impl->p_index = int(identmap.size()); - identmap.push_back(id); - return identmap.back(); + { + std::lock_guard l{ident_mtx}; + idents[id->name()] = id; + impl->p_index = int(identmap.size()); + identmap.push_back(id); + return identmap.back(); + } } ident &internal_state::new_ident(state &cs, std::string_view name, int flags) { @@ -72,6 +98,7 @@ ident &internal_state::new_ident(state &cs, std::string_view name, int flags) { } ident *internal_state::get_ident(std::string_view name) const { + std::lock_guard l{ident_mtx}; auto id = idents.find(name); if (id == idents.end()) { return nullptr; @@ -315,7 +342,7 @@ LIBCUBESCRIPT_EXPORT void *state::alloc(void *ptr, size_t os, size_t ns) { } LIBCUBESCRIPT_EXPORT std::size_t state::ident_count() const { - return p_tstate->istate->identmap.size(); + return p_tstate->istate->get_identnum(); } LIBCUBESCRIPT_EXPORT std::optional< @@ -339,11 +366,11 @@ LIBCUBESCRIPT_EXPORT std::optional< } LIBCUBESCRIPT_EXPORT ident &state::get_ident(std::size_t index) { - return *p_tstate->istate->identmap[index]; + return *p_tstate->istate->lookup_ident(index); } LIBCUBESCRIPT_EXPORT ident const &state::get_ident(std::size_t index) const { - return *p_tstate->istate->identmap[index]; + return *p_tstate->istate->lookup_ident(index); } LIBCUBESCRIPT_EXPORT void state::clear_override(ident &id) { @@ -374,9 +401,9 @@ LIBCUBESCRIPT_EXPORT void state::clear_override(ident &id) { } LIBCUBESCRIPT_EXPORT void state::clear_overrides() { - for (auto &p: p_tstate->istate->idents) { - clear_override(*(p.second)); - } + p_tstate->istate->foreach_ident([](ident *id, void *data) { + static_cast(data)->clear_override(*id); + }, this); } inline int var_flags(bool read_only, var_type vtp) { diff --git a/src/cs_state.hh b/src/cs_state.hh index 108975b..ac4fa8c 100644 --- a/src/cs_state.hh +++ b/src/cs_state.hh @@ -6,6 +6,7 @@ #include #include #include +#include #include "cs_bcode.hh" #include "cs_ident.hh" @@ -49,6 +50,7 @@ struct internal_state { allocator_type > idents; std::vector> identmap; + mutable std::mutex ident_mtx; string_pool *strman; empty_block *empty; @@ -69,6 +71,11 @@ struct internal_state { ~internal_state(); + ident *lookup_ident(std::size_t idx); + ident const *lookup_ident(std::size_t idx) const; + std::size_t get_identnum() const; + void foreach_ident(void (*f)(ident *, void *), void *data); + ident *add_ident(ident *id, ident_impl *impl); ident &new_ident(state &cs, std::string_view name, int flags); ident *get_ident(std::string_view name) const; diff --git a/src/cs_vm.cc b/src/cs_vm.cc index ef06db6..2053259 100644 --- a/src/cs_vm.cc +++ b/src/cs_vm.cc @@ -133,7 +133,7 @@ any_value exec_alias( std::size_t noff = ts.idstack.size(); for(std::size_t i = 0; i < callargs; i++) { auto &ast = ts.get_astack( - static_cast(ts.istate->identmap[i]) + static_cast(ts.istate->lookup_ident(i)) ); auto &st = ts.idstack.emplace_back(); ast.push(st); @@ -167,14 +167,14 @@ any_value exec_alias( tss.ident_flags = oflags; for (std::size_t i = 0; i < cargs; i++) { tss.get_astack( - static_cast(tss.istate->identmap[i]) + static_cast(tss.istate->lookup_ident(i)) ).pop(); amask[i] = false; } for (; amask.any(); ++cargs) { if (amask[cargs]) { tss.get_astack( - static_cast(tss.istate->identmap[cargs]) + static_cast(tss.istate->lookup_ident(cargs)) ).pop(); amask[cargs] = false; } @@ -202,7 +202,7 @@ any_value exec_code_with_args(thread_state &ts, bcode_ref const &body) { for (std::size_t i = 0; mask.any(); ++i) { if (mask[0]) { auto &ast = ts.get_astack( - static_cast(ts.istate->identmap[i]) + static_cast(ts.istate->lookup_ident(i)) ); auto &st = ts.idstack.emplace_back(); st.next = ast.node; @@ -229,7 +229,7 @@ any_value exec_code_with_args(thread_state &ts, bcode_ref const &body) { for (std::size_t i = 0, nredo = 0; mask2.any(); ++i) { if (mask2[0]) { tss.get_astack( - static_cast(tss.istate->identmap[i]) + static_cast(tss.istate->lookup_ident(i)) ).node = tss.idstack[offn + nredo++].next; } mask2 >>= 1; @@ -552,7 +552,7 @@ std::uint32_t *vm_exec( case BC_INST_IDENT: { alias *a = static_cast( - ts.istate->identmap[op >> 8] + ts.istate->lookup_ident(op >> 8) ); if (a->is_arg() && !ident_is_used_arg(a, ts)) { ts.get_astack(a).push(ts.idstack.emplace_back()); @@ -583,7 +583,7 @@ std::uint32_t *vm_exec( goto use_top; case BC_INST_LOOKUP: { - ident *id = ts.istate->identmap[op >> 8]; + ident *id = ts.istate->lookup_ident(op >> 8); if (static_cast(id)->is_arg()) { auto &v = args.emplace_back(); if (ident_is_used_arg(id, ts)) { @@ -617,13 +617,13 @@ std::uint32_t *vm_exec( case BC_INST_VAR: args.emplace_back() = static_cast( - ts.istate->identmap[op >> 8] + ts.istate->lookup_ident(op >> 8) )->value(); goto use_top; case BC_INST_ALIAS: { auto *a = static_cast( - ts.istate->identmap[op >> 8] + ts.istate->lookup_ident(op >> 8) ); auto &ast = ts.get_astack(a); if (a->is_arg()) { @@ -645,7 +645,7 @@ std::uint32_t *vm_exec( case BC_INST_CALL: { result.force_none(); - ident *id = ts.istate->identmap[op >> 8]; + ident *id = ts.istate->lookup_ident(op >> 8); std::size_t callargs = *code++; std::size_t offset = args.size() - callargs; auto *imp = static_cast(id); @@ -768,7 +768,7 @@ noid: case BC_INST_COM: { command_impl *id = static_cast( - ts.istate->identmap[op >> 8] + ts.istate->lookup_ident(op >> 8) ); std::size_t offset = args.size() - id->arg_count(); result.force_none(); @@ -781,7 +781,7 @@ noid: case BC_INST_COM_V: { command_impl *id = static_cast( - ts.istate->identmap[op >> 8] + ts.istate->lookup_ident(op >> 8) ); std::size_t callargs = *code++; std::size_t offset = args.size() - callargs;