From 9a90179a11b433fcbcf587182032222e229c6d75 Mon Sep 17 00:00:00 2001 From: Ernie Rael Date: Tue, 16 Apr 2024 22:11:56 +0200 Subject: patch 9.1.0338: Vim9: import through symlinks not correctly handled Problem: Vim9: import through symlinks not correctly handled Solution: Check for script being a symlink but only once (Ernie Rael) closes: #14565 Signed-off-by: Ernie Rael Signed-off-by: Yegappan Lakshmanan Signed-off-by: Christian Brabandt --- src/proto/scriptfile.pro | 1 + src/scriptfile.c | 37 +++++++++++++++++++++++++++++++++++++ src/structs.h | 1 + src/testdir/test_vim9_import.vim | 27 +++++++++++++++++++++++++++ src/version.c | 2 ++ src/vim9expr.c | 3 +++ 6 files changed, 71 insertions(+) diff --git a/src/proto/scriptfile.pro b/src/proto/scriptfile.pro index dbcc849353..c8ff04a116 100644 --- a/src/proto/scriptfile.pro +++ b/src/proto/scriptfile.pro @@ -9,6 +9,7 @@ void ex_runtime(exarg_T *eap); void set_context_in_runtime_cmd(expand_T *xp, char_u *arg); int find_script_by_name(char_u *name); int get_new_scriptitem_for_fname(int *error, char_u *fname); +void check_script_symlink(int sid); int do_in_path(char_u *path, char *prefix, char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie); int do_in_runtimepath(char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie); int source_runtime(char_u *name, int flags); diff --git a/src/scriptfile.c b/src/scriptfile.c index 109e13e5c6..cc76260410 100644 --- a/src/scriptfile.c +++ b/src/scriptfile.c @@ -405,6 +405,43 @@ get_new_scriptitem_for_fname(int *error, char_u *fname) return sid; } +/* + * If the script for "sid" is a symlink and "sn_source_sid" is not set + * then initialize it. A new script_item is created if needed. + */ + void +check_script_symlink(int sid) +{ + scriptitem_T *si = SCRIPT_ITEM(sid); + if (si->sn_syml_checked || si->sn_sourced_sid > 0) + return; + si->sn_syml_checked = TRUE; + + // If fname is a symbolic link, create an script_item for the real file. + + char_u *real_fname = fix_fname(si->sn_name); + if (real_fname != NULL && STRCMP(real_fname, si->sn_name) != 0) + { + int real_sid = find_script_by_name(real_fname); + int error2 = OK; + int new_sid = FALSE; + if (real_sid < 0) + { + real_sid = get_new_scriptitem_for_fname(&error2, real_fname); + new_sid = TRUE; + } + if (error2 == OK) + { + si = SCRIPT_ITEM(sid); + si->sn_sourced_sid = real_sid; + if (new_sid) + SCRIPT_ITEM(real_sid)->sn_import_autoload + = si->sn_import_autoload; + } + } + vim_free(real_fname); +} + static void find_script_callback(char_u *fname, void *cookie) { diff --git a/src/structs.h b/src/structs.h index f9a72e1454..36339c4347 100644 --- a/src/structs.h +++ b/src/structs.h @@ -2131,6 +2131,7 @@ typedef struct int sn_state; // SN_STATE_ values char_u *sn_save_cpo; // 'cpo' value when :vim9script found char sn_is_vimrc; // .vimrc file, do not restore 'cpo' + char sn_syml_checked;// flag: this has been checked for sym link // for a Vim9 script under "rtp/autoload/" this is "dir#scriptname#" char_u *sn_autoload_prefix; diff --git a/src/testdir/test_vim9_import.vim b/src/testdir/test_vim9_import.vim index 67b67595f5..156b035d48 100644 --- a/src/testdir/test_vim9_import.vim +++ b/src/testdir/test_vim9_import.vim @@ -2930,6 +2930,33 @@ def Test_vim9_import_symlink() unlet g:resultValue &rtp = save_rtp delete('Xfrom', 'rf') + + # Access item from :def imported through symbolic linked directory. #14536 + mkdir('Xto/real_dir', 'pR') + lines =<< trim END + vim9script + export const val = 17 + export def F(): number + return 23 + enddef + END + writefile(lines, 'Xto/real_dir/real_file.vim') + system('ln -s real_dir Xto/syml_dir') + defer delete('Xto/syml_dir') + lines =<< trim END + vim9script + import autoload './Xto/syml_dir/real_file.vim' + + def Fmain() + assert_equal(17, real_file.val) + enddef + def F2() + assert_equal(23, real_file.F()) + enddef + Fmain() + F2() + END + v9.CheckScriptSuccess(lines) endif enddef diff --git a/src/version.c b/src/version.c index 802addc308..d11f808484 100644 --- a/src/version.c +++ b/src/version.c @@ -704,6 +704,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 338, /**/ 337, /**/ diff --git a/src/vim9expr.c b/src/vim9expr.c index ac4d836229..8c412b876d 100644 --- a/src/vim9expr.c +++ b/src/vim9expr.c @@ -546,6 +546,9 @@ compile_load_scriptvar( int done = FALSE; int res = OK; + check_script_symlink(import->imp_sid); + import_check_sourced_sid(&import->imp_sid); + // Need to lookup the member. if (*p != '.') { -- cgit v1.2.3