From 7ba6fea0b7cf9b63688b093151e36f3f34cd78cb Mon Sep 17 00:00:00 2001
From: zeripath <art27@cantab.net>
Date: Fri, 28 Aug 2020 20:55:25 +0100
Subject: [PATCH] Use shellquote to unpack arguments to gitea serv (#12624)

Fix #12471

Signed-off-by: Andrew Thornton <art27@cantab.net>
---
 cmd/serv.go | 33 ++++++++++++++++++---------------
 1 file changed, 18 insertions(+), 15 deletions(-)

diff --git a/cmd/serv.go b/cmd/serv.go
index 7c2be5157a..cccf3de074 100644
--- a/cmd/serv.go
+++ b/cmd/serv.go
@@ -25,6 +25,7 @@ import (
 	"code.gitea.io/gitea/modules/setting"
 
 	"github.com/dgrijalva/jwt-go"
+	"github.com/kballard/go-shellquote"
 	"github.com/unknwon/com"
 	"github.com/urfave/cli"
 )
@@ -59,14 +60,6 @@ func setup(logPath string, debug bool) {
 	}
 }
 
-func parseCmd(cmd string) (string, string) {
-	ss := strings.SplitN(cmd, " ", 2)
-	if len(ss) != 2 {
-		return "", ""
-	}
-	return ss[0], strings.Replace(ss[1], "'/", "'", 1)
-}
-
 var (
 	allowedCommands = map[string]models.AccessMode{
 		"git-upload-pack":    models.AccessModeRead,
@@ -126,7 +119,20 @@ func runServ(c *cli.Context) error {
 		return nil
 	}
 
-	verb, args := parseCmd(cmd)
+	words, err := shellquote.Split(cmd)
+	if err != nil {
+		fail("Error parsing arguments", "Failed to parse arguments: %v", err)
+	}
+
+	if len(words) < 2 {
+		fail("Too few arguments", "Too few arguments in cmd: %s", cmd)
+	}
+
+	verb := words[0]
+	repoPath := words[1]
+	if repoPath[0] == '/' {
+		repoPath = repoPath[1:]
+	}
 
 	var lfsVerb string
 	if verb == lfsAuthenticateVerb {
@@ -134,17 +140,14 @@ func runServ(c *cli.Context) error {
 			fail("Unknown git command", "LFS authentication request over SSH denied, LFS support is disabled")
 		}
 
-		argsSplit := strings.Split(args, " ")
-		if len(argsSplit) >= 2 {
-			args = strings.TrimSpace(argsSplit[0])
-			lfsVerb = strings.TrimSpace(argsSplit[1])
+		if len(words) > 2 {
+			lfsVerb = words[2]
 		}
 	}
 
-	repoPath := strings.ToLower(strings.Trim(args, "'"))
 	rr := strings.SplitN(repoPath, "/", 2)
 	if len(rr) != 2 {
-		fail("Invalid repository path", "Invalid repository path: %v", args)
+		fail("Invalid repository path", "Invalid repository path: %v", repoPath)
 	}
 
 	username := strings.ToLower(rr[0])