From 5d6f2a5ce8f592aaf0dde94f36c354988dc9e862 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Sat, 30 May 2026 19:50:38 +0100 Subject: [PATCH] parse: lex: fix memory leaks --- bshell.runtime/parse/lex/lex-internal.h | 2 +- bshell.runtime/parse/lex/lex.c | 17 ++++++++++++----- bshell.runtime/parse/lex/word.c | 12 +++++++----- bshell.runtime/parse/token.c | 2 ++ 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/bshell.runtime/parse/lex/lex-internal.h b/bshell.runtime/parse/lex/lex-internal.h index 9e48a77..d3b1565 100644 --- a/bshell.runtime/parse/lex/lex-internal.h +++ b/bshell.runtime/parse/lex/lex-internal.h @@ -107,7 +107,7 @@ extern struct bshell_lex_state *lex_state_push( struct bshell_lex_ctx *ctx, enum bshell_lex_state_id state_type, enum state_flags flags); -extern void lex_state_pop(struct bshell_lex_ctx *ctx); +extern void lex_state_pop(struct bshell_lex_ctx *ctx, bool no_preserve_root); extern struct bshell_lex_state *lex_state_get(struct bshell_lex_ctx *ctx); extern void lex_state_change( struct bshell_lex_ctx *ctx, diff --git a/bshell.runtime/parse/lex/lex.c b/bshell.runtime/parse/lex/lex.c index f6522c9..09036f4 100644 --- a/bshell.runtime/parse/lex/lex.c +++ b/bshell.runtime/parse/lex/lex.c @@ -198,11 +198,14 @@ struct bshell_lex_state *lex_state_push( return state; } -void lex_state_pop(struct bshell_lex_ctx *ctx) +void lex_state_pop(struct bshell_lex_ctx *ctx, bool no_preserve_root) { fx_queue_entry *entry = fx_queue_last(&ctx->lex_state); - if (!entry || !fx_queue_prev(entry)) { - /* don't pop if this is the root state */ + if (!entry) { + return; + } + + if (!no_preserve_root && !fx_queue_prev(entry)) { return; } @@ -451,6 +454,10 @@ enum bshell_status bshell_lex_ctx_cleanup(struct bshell_lex_ctx *ctx) fx_string_unref(ctx->lex_tmp); } + while (!fx_queue_empty(&ctx->lex_state)) { + lex_state_pop(ctx, true); + } + memset(ctx, 0x0, sizeof *ctx); return BSHELL_SUCCESS; } @@ -1228,7 +1235,7 @@ static bool do_lex_state_transition( if (!recursive) { for (unsigned int i = 0; i < state->s_nr_terminators; i++) { if (state->s_terminators[i] == token) { - lex_state_pop(ctx); + lex_state_pop(ctx, false); return true; } } @@ -1275,7 +1282,7 @@ static bool do_lex_state_transition( const struct bshell_lex_state_link *link = best_matches[i]; switch (link->l_type) { case BSHELL_LEX_STATE_LINK_POP: - lex_state_pop(ctx); + lex_state_pop(ctx, false); result = true; break; case BSHELL_LEX_STATE_LINK_PUSH: { diff --git a/bshell.runtime/parse/lex/word.c b/bshell.runtime/parse/lex/word.c index 357b43b..44d5d0b 100644 --- a/bshell.runtime/parse/lex/word.c +++ b/bshell.runtime/parse/lex/word.c @@ -21,7 +21,7 @@ static enum bshell_status word_symbol(struct bshell_lex_ctx *ctx) lex_state_push(ctx, BSHELL_LEX_STATE_STATEMENT, 0); return BSHELL_SUCCESS; case BSHELL_SYM_RIGHT_PAREN: - lex_state_pop(ctx); + lex_state_pop(ctx, false); status = push_symbol(ctx, sym->id); if (status != BSHELL_SUCCESS) { @@ -92,7 +92,8 @@ static enum bshell_status word_content(struct bshell_lex_ctx *ctx) static enum bshell_status word_begin(struct bshell_lex_ctx *ctx) { - struct bshell_lex_token *tok = bshell_lex_token_create(BSHELL_TOK_WORD_START); + struct bshell_lex_token *tok + = bshell_lex_token_create(BSHELL_TOK_WORD_START); if (!tok) { return BSHELL_ERR_NO_MEMORY; } @@ -107,7 +108,8 @@ static enum bshell_status word_begin(struct bshell_lex_ctx *ctx) static enum bshell_status word_end(struct bshell_lex_ctx *ctx) { - struct bshell_lex_token *tok = bshell_lex_token_create(BSHELL_TOK_WORD_END); + struct bshell_lex_token *tok + = bshell_lex_token_create(BSHELL_TOK_WORD_END); if (!tok) { return BSHELL_ERR_NO_MEMORY; } @@ -121,12 +123,12 @@ static enum bshell_status word_pump_token(struct bshell_lex_ctx *ctx) fx_wchar c = peek_char(ctx); if (fx_wchar_is_space(c)) { - lex_state_pop(ctx); + lex_state_pop(ctx, false); return BSHELL_SUCCESS; } if (char_has_flags(ctx, c, BSHELL_LEX_TOKEN_TERMINATES_WORD)) { - lex_state_pop(ctx); + lex_state_pop(ctx, false); return BSHELL_SUCCESS; } diff --git a/bshell.runtime/parse/token.c b/bshell.runtime/parse/token.c index 9db3038..aad3f32 100644 --- a/bshell.runtime/parse/token.c +++ b/bshell.runtime/parse/token.c @@ -41,6 +41,8 @@ void bshell_lex_token_destroy(struct bshell_lex_token *tok) switch (tok->tok_type) { case BSHELL_TOK_WORD: case BSHELL_TOK_FLAG: + case BSHELL_TOK_VAR: + case BSHELL_TOK_VAR_SPLAT: case BSHELL_TOK_STRING: if (tok->tok_str) { free(tok->tok_str);