From 87eb7c230eb0d4b01f069e105415b36b1981abf6 Mon Sep 17 00:00:00 2001
From: Guillaume Maudoux <layus.on@gmail.com>
Date: Fri, 26 Feb 2016 22:47:16 +0100
Subject: [PATCH 1/2] Harden system calls to git

---
 autoload/vundle/installer.vim | 46 ++++++++++++++++++++++++++---------
 autoload/vundle/scripts.vim   |  7 ++----
 2 files changed, 36 insertions(+), 17 deletions(-)

diff --git a/autoload/vundle/installer.vim b/autoload/vundle/installer.vim
index 472271a3..3befc9d1 100644
--- a/autoload/vundle/installer.vim
+++ b/autoload/vundle/installer.vim
@@ -343,8 +343,7 @@ endf
 " return -- the URL for the origin remote (string)
 " ---------------------------------------------------------------------------
 func! s:get_current_origin_url(bundle) abort
-  let cmd = 'cd '.vundle#installer#shellesc(a:bundle.path()).' && git config --get remote.origin.url'
-  let cmd = vundle#installer#shellesc_cd(cmd)
+  let cmd = s:make_git_command(a:bundle, ['config', '--get', 'remote.origin.url'])
   let out = s:strip(s:system(cmd))
   return out
 endf
@@ -357,12 +356,37 @@ endf
 " return -- A 15 character log sha for the current HEAD
 " ---------------------------------------------------------------------------
 func! s:get_current_sha(bundle)
-  let cmd = 'cd '.vundle#installer#shellesc(a:bundle.path()).' && git rev-parse HEAD'
-  let cmd = vundle#installer#shellesc_cd(cmd)
+  let cmd = s:make_sync_command(a:bundle, ['rev-parse', 'HEAD'])
   let out = s:system(cmd)[0:15]
   return out
 endf
 
+" ---------------------------------------------------------------------------
+" Build a safe (escaped) git command
+"
+" bundle -- A bundle object to get the path to the git dir
+" args   -- A list of arguments to the git executable
+" return -- A string containing the escaped shell command
+" ---------------------------------------------------------------------------
+func! s:make_git_command(bundle, args) abort
+  let workdir = a:bundle.path()
+  let gitdir  = workdir.'/.git/'
+
+  let git = ['git', '--git-dir='.gitdir, '--work-tree='.workdir]
+
+  return join(map(copy(git + args), 'vundle#installer#shellesc'))
+endf
+
+" ---------------------------------------------------------------------------
+" Build a safe (escaped) command from list of git args
+"
+" bundle -- A bundle object to get the path to the git dir
+" argss  -- A list of lists of arguments to successive git calls
+" return -- A string containing the escaped shell command
+" ---------------------------------------------------------------------------
+func! s:make_git_commands(bundle, argss) abort
+  return join(map(a:argss, 's:make_git_command(s:bundle, {})'), ' && ')
+endf
 
 " ---------------------------------------------------------------------------
 " Create the appropriate sync command to run according to the current state of
@@ -388,14 +412,12 @@ func! s:make_sync_command(bang, bundle) abort
       call s:log('>  Plugin ' . a:bundle.name . ' new URI: ' . a:bundle.uri)
       " Directory names match but the origin remotes are not the same
       let cmd_parts = [
-                  \ 'cd '.vundle#installer#shellesc(a:bundle.path()) ,
-                  \ 'git remote set-url origin ' . vundle#installer#shellesc(a:bundle.uri),
-                  \ 'git fetch',
-                  \ 'git reset --hard origin/HEAD',
-                  \ 'git submodule update --init --recursive',
-                  \ ]
-      let cmd = join(cmd_parts, ' && ')
-      let cmd = vundle#installer#shellesc_cd(cmd)
+          [ 'remote', 'set-url', 'origin', a:bundle.uri ],
+          [ 'fetch' ],
+          [ 'reset', '--hard', 'origin/HEAD' ],
+          [ 'submodule', 'update', '--init', '--recursive' ],
+        ]
+      let cmd = s:make_git_commands(a:bundle, cmd_parts)
       let initial_sha = ''
       return [cmd, initial_sha]
     endif
diff --git a/autoload/vundle/scripts.vim b/autoload/vundle/scripts.vim
index f789762f..1b04c290 100644
--- a/autoload/vundle/scripts.vim
+++ b/autoload/vundle/scripts.vim
@@ -83,11 +83,8 @@ func! s:create_changelog() abort
     let updated_sha = bundle_data[1]
     let bundle      = bundle_data[2]
 
-    let cmd = 'cd '.vundle#installer#shellesc(bundle.path()).
-          \              ' && git log --pretty=format:"%s   %an, %ar" --graph '.
-          \               initial_sha.'..'.updated_sha
-
-    let cmd = vundle#installer#shellesc_cd(cmd)
+    let cmd = s:make_git_command(bundle, ['log', '--pretty=format:"%s   %an, %ar"',
+                    \                     '--graph', initial_sha.'..'.updated_sha ])
 
     let updates = system(cmd)
 

From 462970020bdcd142e1e1cf6134fc0dd100e2ee5e Mon Sep 17 00:00:00 2001
From: Guillaume Maudoux <layus.on@gmail.com>
Date: Fri, 26 Feb 2016 23:30:50 +0100
Subject: [PATCH 2/2] Fix syntax (and other) issues

---
 autoload/vundle/installer.vim | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/autoload/vundle/installer.vim b/autoload/vundle/installer.vim
index 3befc9d1..d35415f0 100644
--- a/autoload/vundle/installer.vim
+++ b/autoload/vundle/installer.vim
@@ -356,7 +356,7 @@ endf
 " return -- A 15 character log sha for the current HEAD
 " ---------------------------------------------------------------------------
 func! s:get_current_sha(bundle)
-  let cmd = s:make_sync_command(a:bundle, ['rev-parse', 'HEAD'])
+  let cmd = s:make_git_command(a:bundle, ['rev-parse', 'HEAD'])
   let out = s:system(cmd)[0:15]
   return out
 endf
@@ -374,7 +374,7 @@ func! s:make_git_command(bundle, args) abort
 
   let git = ['git', '--git-dir='.gitdir, '--work-tree='.workdir]
 
-  return join(map(copy(git + args), 'vundle#installer#shellesc'))
+  return join(map(git + a:args, 'vundle#installer#shellesc(v:val)'))
 endf
 
 " ---------------------------------------------------------------------------
@@ -385,7 +385,7 @@ endf
 " return -- A string containing the escaped shell command
 " ---------------------------------------------------------------------------
 func! s:make_git_commands(bundle, argss) abort
-  return join(map(a:argss, 's:make_git_command(s:bundle, {})'), ' && ')
+  return join(map(a:argss, 's:make_git_command(a:bundle, v:val)'), ' && ')
 endf
 
 " ---------------------------------------------------------------------------
@@ -412,11 +412,11 @@ func! s:make_sync_command(bang, bundle) abort
       call s:log('>  Plugin ' . a:bundle.name . ' new URI: ' . a:bundle.uri)
       " Directory names match but the origin remotes are not the same
       let cmd_parts = [
-          [ 'remote', 'set-url', 'origin', a:bundle.uri ],
-          [ 'fetch' ],
-          [ 'reset', '--hard', 'origin/HEAD' ],
-          [ 'submodule', 'update', '--init', '--recursive' ],
-        ]
+        \  [ 'remote', 'set-url', 'origin', a:bundle.uri ],
+        \  [ 'fetch' ],
+        \  [ 'reset', '--hard', 'origin/HEAD' ],
+        \  [ 'submodule', 'update', '--init', '--recursive' ]
+        \]
       let cmd = s:make_git_commands(a:bundle, cmd_parts)
       let initial_sha = ''
       return [cmd, initial_sha]