From 4a548a033210ff8265a93a5292a847ff4b3abe31 Mon Sep 17 00:00:00 2001 From: zeripath Date: Sun, 23 Aug 2020 14:58:09 +0100 Subject: [PATCH] Fix diff path unquoting (#12554) (#12575) Backport #12554 * Fix diff path unquoting services/gitdiff/gitdiff.go whereby there it assumed that the path would always be quoted on both sides This PR simplifies the code here and uses fmt.Fscanf to parse the strings as necessary. Fix #12546 Signed-off-by: Andrew Thornton * Add testcase as per @mrsdizzie Signed-off-by: Andrew Thornton --- services/gitdiff/gitdiff.go | 47 ++++++++++++-------------------- services/gitdiff/gitdiff_test.go | 17 ++++++++++++ 2 files changed, 34 insertions(+), 30 deletions(-) diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go index 6867f8e0a..268f73ce1 100644 --- a/services/gitdiff/gitdiff.go +++ b/services/gitdiff/gitdiff.go @@ -18,7 +18,6 @@ import ( "os" "os/exec" "sort" - "strconv" "strings" "code.gitea.io/gitea/models" @@ -532,40 +531,28 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D break } - var middle int - // Note: In case file name is surrounded by double quotes (it happens only in git-shell). // e.g. diff --git "a/xxx" "b/xxx" - hasQuote := line[len(cmdDiffHead)] == '"' - if hasQuote { - middle = strings.Index(line, ` "b/`) + var a string + var b string + + rd := strings.NewReader(line[len(cmdDiffHead):]) + char, _ := rd.ReadByte() + _ = rd.UnreadByte() + if char == '"' { + fmt.Fscanf(rd, "%q ", &a) } else { - middle = strings.Index(line, " b/") + fmt.Fscanf(rd, "%s ", &a) } - - beg := len(cmdDiffHead) - a := line[beg+2 : middle] - b := line[middle+3:] - - if hasQuote { - // Keep the entire string in double quotes for now - a = line[beg:middle] - b = line[middle+1:] - - var err error - a, err = strconv.Unquote(a) - if err != nil { - return nil, fmt.Errorf("Unquote: %v", err) - } - b, err = strconv.Unquote(b) - if err != nil { - return nil, fmt.Errorf("Unquote: %v", err) - } - // Now remove the /a /b - a = a[2:] - b = b[2:] - + char, _ = rd.ReadByte() + _ = rd.UnreadByte() + if char == '"' { + fmt.Fscanf(rd, "%q", &b) + } else { + fmt.Fscanf(rd, "%s", &b) } + a = a[2:] + b = b[2:] curFile = &DiffFile{ Name: b, diff --git a/services/gitdiff/gitdiff_test.go b/services/gitdiff/gitdiff_test.go index efdf43993..ec468b1e7 100644 --- a/services/gitdiff/gitdiff_test.go +++ b/services/gitdiff/gitdiff_test.go @@ -76,6 +76,23 @@ func TestParsePatch(t *testing.T) { } println(result) + var diff2a = `diff --git "a/A \\ B" b/A/B +--- "a/A \\ B" ++++ b/A/B +@@ -1,3 +1,6 @@ + # gitea-github-migrator ++ ++ Build Status +- Latest Release + Docker Pulls ++ cut off ++ cut off` + result, err = ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff2a)) + if err != nil { + t.Errorf("ParsePatch failed: %s", err) + } + println(result) + var diff3 = `diff --git a/README.md b/README.md --- a/README.md +++ b/README.md