Bug#493937: [Patch] Prevent loading of Python modules in working directory

Bram Moolenaar Bram at moolenaar.net
Thu Nov 13 10:23:07 UTC 2008


James -

> > > Vim's python interface calls PySys_SetArgv with an argv[0] that doesn't
> > > resolve to a filename.  This causes Python to prepend sys.path with an
> > > empty string which, due to Python's use of relative imports, allows the
> > > possibility to run arbitrary code on the user's system if a file in
> > > Vim's working directory matches the name of a python module a
> > > Python-using vim script tries to import.
> > > 
> > > This should be fixed by Python 2.6 as it uses absolute imports by
> > > default, but I have not been able to test it.  The attached patch fixes
> > > the problem in Vim by removing any empty strings from sys.path.
> > 
> > I have now applied and tried this patch.  It does not really work as
> > expected for me.  Apparently the empty string in argv[0] is interpreted
> > as the current directory.
> 
> argv[0] is used to seed the value that is prepended to sys.path.
> 
> You can take a look at what PySys_SetArgv does at
> http://svn.python.org/view/python/branches/release25-maint/Python/sysmodule.c?rev=54836&view=markup
> 
> What it boils down to in the simple case is checking for the existence
> of a path separator in argv0.  If that doesn't exist, then a PyString is
> created from argv0 with size 0 and sys.path is prepended with that --
> empty string used for the first element of sys.path.
> 
> > My first entry in sys.path is then the directory above the current
> > directory.  The filter you added in the patch doesn't change anything.
> 
> This is incorrect.  In Vim's current code, PySys_SetArgv is called with
> an argv that is simply an empty string (and a terminating NULL
> sentinel).  This causes sys.path's first element to be the empty string,
> thus causing any Python import statements to use Vim's current working
> directory as the first location to check for the requested module.
> 
> The filter specifically removes any elements in sys.path that evaluate
> to false (i.e., the empty string).

That is not what happens for me.  Somehow somewhere the empty entry is
changed to the full path of the directory above the current directory.
I don't know where, but I see it happening.  I have tried this with:

	:py import sys
	:py print sys.path

> Using the attached print_sys.path.diff, the following is printed when I
> start Vim (the sys.path before and after my suggested filter() command):
> 
> ['', '/usr/lib/python2.5', '/usr/lib/python2.5/plat-linux2', '/usr/lib/python2.5/lib-tk', '/usr/lib/python2.5/lib-dynload', '/usr/local/lib/python2.5/site-packages', '/usr/lib/python2.5/site-packages']
> ['/usr/lib/python2.5', '/usr/lib/python2.5/plat-linux2', '/usr/lib/python2.5/lib-tk', '/usr/lib/python2.5/lib-dynload', '/usr/local/lib/python2.5/site-packages', '/usr/lib/python2.5/site-packages']

As mentioned, for me the first entry is not '' but a path.   The filter
command you suggested doesn't remove it.  I don't know where the
difference between our systems comes from.

> You can also test it with the simple pytest.c that I've attached by
> specifying different arguments as the first element of the argv passed
> to PySys_SetArgv.
> 
> $ gcc -o pytest $(python-config --cflags) $(python-config --ldflags) pytest.c
> $ ./pytest ''
> ['', '/usr/lib/python2.5', '/usr/lib/python2.5/plat-linux2', '/usr/lib/python2.5/lib-tk', '/usr/lib/python2.5/lib-dynload', '/usr/local/lib/python2.5/site-packages', '/usr/lib/python2.5/site-packages']
> ['/usr/lib/python2.5', '/usr/lib/python2.5/plat-linux2', '/usr/lib/python2.5/lib-tk', '/usr/lib/python2.5/lib-dynload', '/usr/local/lib/python2.5/site-packages', '/usr/lib/python2.5/site-packages']
> $ ./pytest '/must>not&exist/bogusbinary'
> ['/must>not&exist', '/usr/lib/python2.5', '/usr/lib/python2.5/plat-linux2', '/usr/lib/python2.5/lib-tk', '/usr/lib/python2.5/lib-dynload', '/usr/local/lib/python2.5/site-packages', '/usr/lib/python2.5/site-packages']
> ['/must>not&exist', '/usr/lib/python2.5', '/usr/lib/python2.5/plat-linux2', '/usr/lib/python2.5/lib-tk', '/usr/lib/python2.5/lib-dynload', '/usr/local/lib/python2.5/site-packages', '/usr/lib/python2.5/site-packages']
> 
> > For me it does work if I use:
> > 
> >    static char *(argv[2]) = {"/must>not&exist/ls", NULL};
> > 
> > The first entry in path is then "/must>not&exist", which we can filter
> > out with:
> > 
> >    PyRun_SimpleString("import sys; sys.path = filter(lambda x: x != '/must>not&exist', sys.path)");
> 
> This is just extra work for no gain.

It does work for me.  Does it also work for you?

- Bram

-- 
hundred-and-one symptoms of being an internet addict:
249. You've forgotten what the outside looks like.

 /// Bram Moolenaar -- Bram at Moolenaar.net -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\        download, build and distribute -- http://www.A-A-P.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///





More information about the pkg-vim-maintainers mailing list