patch 9.1.0338: Vim9: import through symlinks not correctly handled

Commit: 
https://github.com/vim/vim/commit/9a90179a11b433fcbcf587182032222e229c6d75
Author: Ernie Rael <err...@raelity.com>
Date:   Tue Apr 16 22:11:56 2024 +0200

    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 <err...@raelity.com>
    Signed-off-by: Yegappan Lakshmanan <yegap...@yahoo.com>
    Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/src/proto/scriptfile.pro b/src/proto/scriptfile.pro
index dbcc84935..c8ff04a11 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 109e13e5c..cc7626041 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 f9a72e145..36339c434 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 67b67595f..156b035d4 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 802addc30..d11f80848 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 ac4d83622..8c412b876 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 != '.')
        {

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/E1rwpRM-00EYAV-MF%40256bit.org.

Raspunde prin e-mail lui