From 49eca6f2df31672e5b557bf5c420c3c0f0fdb8f4 Mon Sep 17 00:00:00 2001 From: "Gu://em_" Date: Fri, 30 Jan 2026 20:58:10 +0100 Subject: [PATCH 1/3] fix: random parser fixes --- src/parser/grammar_basic.c | 85 ++++++++++++++++++++++++++++---------- 1 file changed, 63 insertions(+), 22 deletions(-) diff --git a/src/parser/grammar_basic.c b/src/parser/grammar_basic.c index b7f58bd..f0f96f9 100644 --- a/src/parser/grammar_basic.c +++ b/src/parser/grammar_basic.c @@ -68,8 +68,13 @@ struct ast *parse_list(struct lexer_context *ctx) token = PEEK_TOKEN(); while (token->type == TOKEN_SEMICOLON) { - token = POP_TOKEN(); + // Forward + POP_TOKEN(); token = PEEK_TOKEN(); + + // TODO seems a little akward (not fully compliant with the grammar) + // but it's time consuming to rewrite to only cover edge cases. + // So it'll probably stay like that for now if (is_first(*token, RULE_AND_OR)) { current_node = parse_and_or(ctx); @@ -304,8 +309,26 @@ struct ast *parse_element(struct lexer_context *ctx) struct token *token = PEEK_TOKEN(); if (token->type == TOKEN_WORD || token->type == TOKEN_ASSIGNMENT_WORD) { - token = POP_TOKEN(); - return ast_create_word(token->data); + POP_TOKEN(); + + char *word = strdup(token->data); + if (word == NULL) + { + perror("Internal error: could not copy token data (is your memory " + "full ?)"); + return NULL; + } + + struct ast *result = ast_create_word(word); + if (result == NULL) + { + perror("Internal error: could not create ast node (is your memory " + "full ?)"); + free(word); + return NULL; + } + + return result; } else if (token->type == TOKEN_IONUMBER || is_token_redir(token)) { @@ -378,12 +401,15 @@ struct ast *parse_if_rule(struct lexer_context *ctx) // Condition content struct ast *condition_content = parse_compound_list(ctx); + if (condition_content == NULL) + return NULL; + token = PEEK_TOKEN(); // Then keyword - token = PEEK_TOKEN(); if (token->type != TOKEN_THEN) { - perror("Expected the 'then' keyword but token has different type"); + perror("Syntax error: Expected the 'then' keyword but token has " + "different type"); return err_if_rule(&condition_content, NULL, NULL); } POP_TOKEN(); @@ -394,9 +420,9 @@ struct ast *parse_if_rule(struct lexer_context *ctx) { return err_if_rule(&condition_content, &then_content, NULL); } + token = PEEK_TOKEN(); struct ast *else_content = NULL; - token = PEEK_TOKEN(); // Eventual else/elif clause(s) if (is_first(*token, RULE_ELSE_CLAUSE)) { @@ -405,10 +431,10 @@ struct ast *parse_if_rule(struct lexer_context *ctx) { return err_if_rule(&condition_content, &then_content, NULL); } + token = PEEK_TOKEN(); } // Fi keyword - token = PEEK_TOKEN(); if (token->type != TOKEN_FI) { perror("Expected the 'fi' keyword but token has different type"); @@ -437,7 +463,7 @@ struct ast *parse_compound_list(struct lexer_context *ctx) // Skip newlines while (token->type == TOKEN_NEWLINE) { - token = POP_TOKEN(); + POP_TOKEN(); token = PEEK_TOKEN(); } @@ -446,9 +472,9 @@ struct ast *parse_compound_list(struct lexer_context *ctx) if (current_cmd == NULL) return NULL; result_list = list_append(result_list, current_cmd); + token = PEEK_TOKEN(); // Following commands - token = PEEK_TOKEN(); while (token->type == TOKEN_SEMICOLON || token->type == TOKEN_NEWLINE) { POP_TOKEN(); @@ -457,7 +483,7 @@ struct ast *parse_compound_list(struct lexer_context *ctx) // Skip newlines while (token->type == TOKEN_NEWLINE) { - token = POP_TOKEN(); + POP_TOKEN(); token = PEEK_TOKEN(); } @@ -468,22 +494,21 @@ struct ast *parse_compound_list(struct lexer_context *ctx) if (current_cmd == NULL) return NULL; result_list = list_append(result_list, current_cmd); + token = PEEK_TOKEN(); } - - token = PEEK_TOKEN(); } - // Eventual semicolons + // Eventual semicolon if (token->type == TOKEN_SEMICOLON) { - token = POP_TOKEN(); + POP_TOKEN(); token = PEEK_TOKEN(); } // Skip newlines while (token->type == TOKEN_NEWLINE) { - token = POP_TOKEN(); + POP_TOKEN(); token = PEEK_TOKEN(); } @@ -513,18 +538,31 @@ struct ast *parse_else_clause(struct lexer_context *ctx) // Then clause struct ast *then_content = parse_compound_list(ctx); + if (then_content == NULL) + { + ast_free(&condition); + return NULL; + } + token = PEEK_TOKEN(); // Eventual else clause (recursive) struct ast *else_content = NULL; - token = PEEK_TOKEN(); if (token->type == TOKEN_ELSE || token->type == TOKEN_ELIF) { else_content = parse_else_clause(ctx); + if (else_content == NULL) + { + ast_free(&then_content); + ast_free(&condition); + return NULL; + } + } + else + { + else_content = ast_create_void(); } - struct ast *result = - ast_create_if(condition, then_content, else_content); - return result; + return ast_create_if(condition, then_content, else_content); } // Eventual else content @@ -533,12 +571,15 @@ struct ast *parse_else_clause(struct lexer_context *ctx) if (token->type == TOKEN_ELSE) { - token = POP_TOKEN(); // eat else + token = POP_TOKEN(); result = parse_compound_list(ctx); + if (result == NULL) + return NULL; } - - if (result == NULL) + else + { result = ast_create_void(); + } return result; } From b663655d53da3e1abf0815d3153aa12bd99ccfd8 Mon Sep 17 00:00:00 2001 From: "Gu://em_" Date: Fri, 30 Jan 2026 21:27:23 +0100 Subject: [PATCH 2/3] fix: strdup a la con --- src/parser/grammar_basic.c | 18 ++++-------------- src/utils/ast/ast_word.c | 5 +++-- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/src/parser/grammar_basic.c b/src/parser/grammar_basic.c index dcd6b31..df103fc 100644 --- a/src/parser/grammar_basic.c +++ b/src/parser/grammar_basic.c @@ -304,13 +304,12 @@ struct ast *parse_simple_command(struct lexer_context *ctx) // Get element type if (ast_is_word(element)) { + // Extract word struct ast_word *element_word = ast_get_word(element); - - // TODO test this fix for the memory leaks - char *word = strdup(element_word->word); + char *word = element_word->word; + element_word->word = NULL; // Prevents word to be freed ast_free(&element); command_elements = list_append(command_elements, word); - // end of fix } else if (ast_is_redir(element)) { @@ -344,20 +343,11 @@ struct ast *parse_element(struct lexer_context *ctx) { POP_TOKEN(); - char *word = strdup(token->data); - if (word == NULL) - { - perror("Internal error: could not copy token data (is your memory " - "full ?)"); - return NULL; - } - - struct ast *result = ast_create_word(word); + struct ast *result = ast_create_word(token->data); if (result == NULL) { perror("Internal error: could not create ast node (is your memory " "full ?)"); - free(word); return NULL; } diff --git a/src/utils/ast/ast_word.c b/src/utils/ast/ast_word.c index 6870c50..d83489c 100644 --- a/src/utils/ast/ast_word.c +++ b/src/utils/ast/ast_word.c @@ -2,7 +2,6 @@ #include "ast_word.h" #include -#include #include #include @@ -43,6 +42,8 @@ void ast_free_word(struct ast_word *ast_node) if (ast_node == NULL) return; - free(ast_node->word); + if (ast_node->word != NULL) + free(ast_node->word); + free(ast_node); } From 3794ee0253b68a556889cc327ca57cea891fefb3 Mon Sep 17 00:00:00 2001 From: "Gu://em_" Date: Fri, 30 Jan 2026 21:29:39 +0100 Subject: [PATCH 3/3] fix: pourcent --- tests/functional/run-tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/run-tests.sh b/tests/functional/run-tests.sh index c21ee88..5119aad 100755 --- a/tests/functional/run-tests.sh +++ b/tests/functional/run-tests.sh @@ -251,7 +251,7 @@ summarize() { # Print echo -e $BWhite "\n\n""===========" $UWhite"Summary"$Color_Off "\n" - echo -e " Passed $coverage_color$passed_tests/$total_tests$Color_Off tests ($coverage_color$tests_percentage$Color_Off%)" + echo -e " Passed $coverage_color$passed_tests/$total_tests$Color_Off tests ($coverage_color$tests_percentage%$Color_Off)" echo -e " Got $timeouts_color$timeouts_count timeout(s)$Color_Off" if [ "$OUTPUT_FILE" != "" ]; then echo $tests_percentage > "$OUTPUT_FILE";