From e073377e9bb81c1a9c6d9697beeebff909c3bbd3 Mon Sep 17 00:00:00 2001 From: id_pschernig Date: Wed, 22 Oct 2025 16:12:24 +0200 Subject: [PATCH 1/5] Fix problem with calculation of the 'c_ast.FuncDecl' offset --- nala/dist/nala.c | 6 +++--- nala/inspect.py | 10 ++++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/nala/dist/nala.c b/nala/dist/nala.c index f24c78d..ff7908d 100644 --- a/nala/dist/nala.c +++ b/nala/dist/nala.c @@ -3360,7 +3360,7 @@ void nala_subprocess_result_free(struct nala_subprocess_result_t *self_p) // #include "subprocess.h" -#define DEPTH_MAX 100 +#define NALA_DEPTH_MAX 100 #define ANSI_COLOR_GREEN "\x1b[32m" #define ANSI_COLOR_CYAN "\x1b[36m" @@ -3603,9 +3603,9 @@ char *nala_traceback_string(const char *prefix_p, void *arg_p) { int depth; - void *addresses[DEPTH_MAX]; + void *addresses[NALA_DEPTH_MAX]; - depth = backtrace(&addresses[0], DEPTH_MAX); + depth = backtrace(&addresses[0], NALA_DEPTH_MAX); return (nala_traceback_format(addresses, depth, diff --git a/nala/inspect.py b/nala/inspect.py index b26ecc0..2d56946 100644 --- a/nala/inspect.py +++ b/nala/inspect.py @@ -390,6 +390,16 @@ def parse(self): self.typedefs_code + self.structs_code + self.func_signatures) self.file_ast = self.cparser.parse(code) func_offset = len(self.typedefs_code + self.structs_code) + # PATCH BEGIN + # The above offset calculation sometimes doesn't point to the first element of + # type 'c_ast.FuncDecl'. In that case we use the below search to find the first + # 'c_ast.FuncDecl' and take this index as offset. + if not isinstance(self.file_ast.ext[func_offset].type, c_ast.FuncDecl): + for i in range(len(self.file_ast.ext)): + if isinstance(self.file_ast.ext[i].type, c_ast.FuncDecl): + func_offset = i + break + # PATCH END for i, func_name in enumerate(self.func_names, func_offset): if self.param_names is None: From 897818fb106cbcfdcbe4d87a67b1e199e8713c43 Mon Sep 17 00:00:00 2001 From: id_pschernig Date: Thu, 23 Oct 2025 09:37:46 +0200 Subject: [PATCH 2/5] Fix problem with calculation of the 'c_ast.FuncDecl' offset in cases where function pointer typedefs are present in the translation unit. --- nala/inspect.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/nala/inspect.py b/nala/inspect.py index 2d56946..449fcf9 100644 --- a/nala/inspect.py +++ b/nala/inspect.py @@ -391,11 +391,15 @@ def parse(self): self.file_ast = self.cparser.parse(code) func_offset = len(self.typedefs_code + self.structs_code) # PATCH BEGIN - # The above offset calculation sometimes doesn't point to the first element of - # type 'c_ast.FuncDecl'. In that case we use the below search to find the first - # 'c_ast.FuncDecl' and take this index as offset. + # The above offset calculation sometimes ends up giving a wrong start index. + # As a result the first function_declaration handed over to `rename_parameters` + # is of type 'Struct' which has no argument 'args'! + # Now we test if the element at index `func_offset` has the correct type, and if + # not the AST list is searched for the first 'c_ast.FuncDecl' starting from the + # calculated `func_offset`. The index of the first detected 'c_ast.FuncDecl' is + # then used as new `func_offset`! if not isinstance(self.file_ast.ext[func_offset].type, c_ast.FuncDecl): - for i in range(len(self.file_ast.ext)): + for i in range(func_offset, len(self.file_ast.ext)): if isinstance(self.file_ast.ext[i].type, c_ast.FuncDecl): func_offset = i break From 3fee5ac76f0c590c3c7f6e6e4c00d7d410bbfc2f Mon Sep 17 00:00:00 2001 From: id_pschernig Date: Thu, 23 Oct 2025 19:14:03 +0200 Subject: [PATCH 3/5] fix first bug introduced by pull request --- nala/inspect.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nala/inspect.py b/nala/inspect.py index 449fcf9..2c1d30c 100644 --- a/nala/inspect.py +++ b/nala/inspect.py @@ -398,7 +398,7 @@ def parse(self): # not the AST list is searched for the first 'c_ast.FuncDecl' starting from the # calculated `func_offset`. The index of the first detected 'c_ast.FuncDecl' is # then used as new `func_offset`! - if not isinstance(self.file_ast.ext[func_offset].type, c_ast.FuncDecl): + if func_offset < len(self.file_ast.ext) and not isinstance(self.file_ast.ext[func_offset].type, c_ast.FuncDecl): for i in range(func_offset, len(self.file_ast.ext)): if isinstance(self.file_ast.ext[i].type, c_ast.FuncDecl): func_offset = i From 70d3cd027b22a83f573ff740d8e38649a870139c Mon Sep 17 00:00:00 2001 From: id_pschernig Date: Thu, 23 Oct 2025 19:15:01 +0200 Subject: [PATCH 4/5] fix several bugs introduced with newer gcc versions (especially gcc 15.2) --- tests/test_command_line.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_command_line.py b/tests/test_command_line.py index 78ec6d2..42ebec2 100644 --- a/tests/test_command_line.py +++ b/tests/test_command_line.py @@ -31,6 +31,7 @@ def remove_optput(): def pre_process_file(name): command = [ 'gcc', + '-std=c11', '-E', '-I', 'nala/dist', '-o', f'tests/files/{name}/test_tests.pp.c', From abb354df59ce0cc95ba599e9dfc6b4fc8c7ba2fb Mon Sep 17 00:00:00 2001 From: id_pschernig Date: Sun, 26 Oct 2025 12:02:05 +0100 Subject: [PATCH 5/5] fix pycparser problem with 128-bit types --- .github/workflows/test.yml | 8 ++++---- nala/inspect.py | 10 ++++++++++ tests/test_command_line.py | 2 +- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3244360..0af9e31 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,11 +4,11 @@ on: [push, pull_request] jobs: test: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 strategy: max-parallel: 4 matrix: - python-version: [3.9] + python-version: ['3.13'] steps: - uses: actions/checkout@v1 - name: Set up Python ${{ matrix.python-version }} @@ -34,10 +34,10 @@ jobs: steps: - name: Checkout uses: actions/checkout@v1 - - name: Set up Python 3.9 + - name: Set up Python 3.13 uses: actions/setup-python@v1 with: - python-version: 3.9 + python-version: '3.13' - name: Install pypa/build run: | python -m pip install build --user diff --git a/nala/inspect.py b/nala/inspect.py index 2c1d30c..a1c8ef4 100644 --- a/nala/inspect.py +++ b/nala/inspect.py @@ -386,6 +386,16 @@ def parse(self): if self.functions: return + # PATCH BEGIN + # It turns out that at least gcc 15.2 outputs typedefs using '__int128' during preproccesing + # step which is not parsable by pycparser. For this reason we simply removeall 128-bit typedefs here! + typedefs_code = [] + for elem in self.typedefs_code: + if "__int128" in elem: + continue + typedefs_code.append(elem) + self.typedefs_code = typedefs_code + # PATCH END code = '\n'.join( self.typedefs_code + self.structs_code + self.func_signatures) self.file_ast = self.cparser.parse(code) diff --git a/tests/test_command_line.py b/tests/test_command_line.py index 42ebec2..027955d 100644 --- a/tests/test_command_line.py +++ b/tests/test_command_line.py @@ -31,7 +31,7 @@ def remove_optput(): def pre_process_file(name): command = [ 'gcc', - '-std=c11', + '-std=c17', # this avoids gcc to use gnu extensions, which are not supported by pycparser '-E', '-I', 'nala/dist', '-o', f'tests/files/{name}/test_tests.pp.c',