Skip to content

Commit 36cfb8c

Browse files
committed
fix(include): snapshot base_dir at load_file_into_program entry
base_dir was aliased to get_base_dir()'s static buffer at the call site. A nested #INCLUDE "../foo" recursive call recomputed get_base_dir() inside the recursion, overwriting that buffer — so when the recursion returned, the parent's view of *its own* directory was now the included file's directory. The parent's next #INCLUDE in the same file then resolved against the wrong base. Concrete failure: shooter.bas at /shooter/shooter.bas with #INCLUDE "../maplib.bas" #INCLUDE "level1.bas" The first include recursed into /shooter/../maplib.bas; on return shooter.bas's base_dir had been clobbered to "/shooter/..", so "level1.bas" resolved to "/shooter/../level1.bas" (no such file) and basic-gfx exit(1)'d with "Cannot open …". Fix: copy base_dir into a stack-local buffer at function entry and re-point the parameter at it. Each recursion now has its own stable base_dir even though get_base_dir's static is shared. Test added: tests/include_chain_test.bas + include_chain/main.bas + inner.bas + include_chain_lib.bas — two-include chain that pre-fix exit(1)'d on the second include and now returns 18 (7+11).
1 parent 7129f57 commit 36cfb8c

5 files changed

Lines changed: 37 additions & 0 deletions

File tree

basic.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15883,6 +15883,16 @@ static void load_file_into_program(const char *path, const char *base_dir, int i
1588315883
int number;
1588415884
const char *resolved;
1588515885
int i;
15886+
/* Snapshot base_dir into a stack-local buffer. The caller's `base_dir`
15887+
* may alias get_base_dir's static buffer, which our recursive
15888+
* #INCLUDE call would overwrite — corrupting the parent's view of
15889+
* its own directory and breaking the second include in a row. */
15890+
char base_dir_local[MAX_INCLUDE_PATH];
15891+
if (base_dir) {
15892+
strncpy(base_dir_local, base_dir, sizeof(base_dir_local) - 1);
15893+
base_dir_local[sizeof(base_dir_local) - 1] = '\0';
15894+
base_dir = base_dir_local;
15895+
}
1588615896

1588715897
if (include_depth >= MAX_INCLUDE_DEPTH) {
1588815898
fprintf(stderr, "Include nesting too deep: %s\n", path);

tests/include_chain/inner.bas

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
REM Same-dir include; would resolve incorrectly if the parent's
2+
REM base_dir had been overwritten by the previous "../" include.
3+
FUNCTION inner_value()
4+
RETURN 11
5+
END FUNCTION

tests/include_chain/main.bas

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
REM Two includes in a row: first uses "../" (overwrote the
2+
REM aliased-static base_dir buffer pre-fix), second is a sibling
3+
REM that pre-fix resolved against the corrupted dir and exit(1)'d.
4+
#INCLUDE "../include_chain_lib.bas"
5+
#INCLUDE "inner.bas"
6+
7+
FUNCTION main_value()
8+
RETURN inner_value() + lib_value()
9+
END FUNCTION

tests/include_chain_lib.bas

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
REM Sibling-of-parent lib (one level up from main.bas).
2+
FUNCTION lib_value()
3+
RETURN 7
4+
END FUNCTION

tests/include_chain_test.bas

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
REM Regression: load_file_into_program's `base_dir` aliased
2+
REM get_base_dir's static buffer. A nested #INCLUDE "../foo" inside
3+
REM main.bas overwrote that buffer, so main.bas's *next* include
4+
REM resolved against the corrupted directory and basic-gfx exit(1)'d
5+
REM with "Cannot open …". Fixed by snapshotting base_dir into a
6+
REM stack-local buffer at function entry.
7+
#INCLUDE "include_chain/main.bas"
8+
9+
PRINT main_value()

0 commit comments

Comments
 (0)