From 7683429f76b64fe5a3077a6b7164868d1e20d1d8 Mon Sep 17 00:00:00 2001 From: zeripath Date: Thu, 16 Dec 2021 17:40:18 +0000 Subject: [PATCH 1/3] Prevent double decoding of % in url params (#17997) There was an unfortunate regression in #14293 which has led to the double decoding of url parameter elements if they contain a '%'. This is due to an issue with the way chi decodes its RoutePath. In detail the problem lies in mux.go where the routeHTTP path uses the URL.RawPath or even the URL.Path instead of the escaped path to do routing. This PR simply forcibly sets the routePath to that of the EscapedPath. Fix #17938 Signed-off-by: Andrew Thornton --- .../4c/61dd0a799e0830e77edfe6c74f7c349bc8e62a | Bin 0 -> 40 bytes .../50/4d9fe743979d4e9785a25a363c7007293f0838 | Bin 0 -> 40 bytes .../59/e2c41e8f5140bb0182acebec17c8ad9831cc62 | Bin 0 -> 847 bytes .../64/89894ad11093fdc49c0ed857d80682344a7264 | Bin 0 -> 39 bytes .../84/7c6d93c6860dd377651245711b7fbcd34a18d4 | Bin 0 -> 41 bytes .../9b/9cc8f558d1c4f815592496fa24308ba2a9c824 | Bin 0 -> 47 bytes .../a4/f1bb3f2f8c6a0e840e935812ef4903ce515dad | Bin 0 -> 394 bytes .../c7/85b65bf16928b58567cb23669125c0ccd25a4f | Bin 0 -> 44 bytes .../e9/63733b8a355cf860c465b4af7b236a6ef08783 | Bin 0 -> 47 bytes .../utf8.git/refs/heads/Plus+Is+Not+Space | 2 +- integrations/nonascii_branches_test.go | 36 ++++++++++++++++++ modules/context/context.go | 4 ++ 12 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 integrations/gitea-repositories-meta/user2/utf8.git/objects/4c/61dd0a799e0830e77edfe6c74f7c349bc8e62a create mode 100644 integrations/gitea-repositories-meta/user2/utf8.git/objects/50/4d9fe743979d4e9785a25a363c7007293f0838 create mode 100644 integrations/gitea-repositories-meta/user2/utf8.git/objects/59/e2c41e8f5140bb0182acebec17c8ad9831cc62 create mode 100644 integrations/gitea-repositories-meta/user2/utf8.git/objects/64/89894ad11093fdc49c0ed857d80682344a7264 create mode 100644 integrations/gitea-repositories-meta/user2/utf8.git/objects/84/7c6d93c6860dd377651245711b7fbcd34a18d4 create mode 100644 integrations/gitea-repositories-meta/user2/utf8.git/objects/9b/9cc8f558d1c4f815592496fa24308ba2a9c824 create mode 100644 integrations/gitea-repositories-meta/user2/utf8.git/objects/a4/f1bb3f2f8c6a0e840e935812ef4903ce515dad create mode 100644 integrations/gitea-repositories-meta/user2/utf8.git/objects/c7/85b65bf16928b58567cb23669125c0ccd25a4f create mode 100644 integrations/gitea-repositories-meta/user2/utf8.git/objects/e9/63733b8a355cf860c465b4af7b236a6ef08783 diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/objects/4c/61dd0a799e0830e77edfe6c74f7c349bc8e62a b/integrations/gitea-repositories-meta/user2/utf8.git/objects/4c/61dd0a799e0830e77edfe6c74f7c349bc8e62a new file mode 100644 index 0000000000000000000000000000000000000000..17b3104773bbfb8ccdb5084cd6dda8a5ec794098 GIT binary patch literal 40 ycmV+@0N4L`0ZYosPf{>4VJObXFU?6&$jdKLNJ>?(&n!-~Ps_|nlhEoiLBnXFNksc<6)~1Zn7b`1t8Qd&I=Btb+4C072*vod5s; literal 0 HcmV?d00001 diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/objects/59/e2c41e8f5140bb0182acebec17c8ad9831cc62 b/integrations/gitea-repositories-meta/user2/utf8.git/objects/59/e2c41e8f5140bb0182acebec17c8ad9831cc62 new file mode 100644 index 0000000000000000000000000000000000000000..736a24227c153003864cb1b41e751db5af19f495 GIT binary patch literal 847 zcmV-V1F-yf0d14X&Z9^Wgy+mt)E!N;nnmg!HLJ~H3b*{pZE#8vBlre z(ES4#fs+MB;AI|=^hd;per{Xv1e89T@CKsKf_@o#@EuMIEB-{VUts#J$IBn4i?Nui z0{s22RAX;>z~B2IwDz77#b@I;CjbGezD-`MUl`0(RQ??VYon<|1+dJJzJ4vt7j1R-e!YFkQ zU$TFYkIa!N$O5gob;AUBCCn&0O;l$G%*YnAb37+Fi|k{u%-5{P<3j4LDBhcK>#OMr-tw}Zcv6-$9v*tZ#VH8%74c31t4hLsNwl)NKV)s@1|Mi>8U zAIOMDeCDEC5nuKM=uVAseVsLm@@*=S9Fe~Y1HjTO8Ei7kXo&;$z$ z6{vYE$x)N0XdfSJlId;g{J1W)CtP)vjGf7oB2G^a#hlH_md&ZeLHP_cRCj~V%V`EEeTT{)P`<4^EgMpDXPYUZj*Dn=sI)Tb%cjx{2H4Tg=H#B)wmUPvmDb&Ja{W>5cgZ0e;xjl_UPkjN$2j ZN(`Z78R&)y1H4u($g395#4n|VR?zITsw@Bi literal 0 HcmV?d00001 diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/objects/64/89894ad11093fdc49c0ed857d80682344a7264 b/integrations/gitea-repositories-meta/user2/utf8.git/objects/64/89894ad11093fdc49c0ed857d80682344a7264 new file mode 100644 index 0000000000000000000000000000000000000000..87e198aa9ca2e9f95e3fa41a231e50e697b131af GIT binary patch literal 39 vcmb2lZ0;dW9HS!N? literal 0 HcmV?d00001 diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/objects/84/7c6d93c6860dd377651245711b7fbcd34a18d4 b/integrations/gitea-repositories-meta/user2/utf8.git/objects/84/7c6d93c6860dd377651245711b7fbcd34a18d4 new file mode 100644 index 0000000000000000000000000000000000000000..ffea321c19db661925c77ef5367155c13ba0b308 GIT binary patch literal 41 xcmbQM8W(dj1ELH%b!qUu=RE5Mmh19al9EH5Z+|(3>w9K4TE&v;G F4X_eV7Igps literal 0 HcmV?d00001 diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/objects/a4/f1bb3f2f8c6a0e840e935812ef4903ce515dad b/integrations/gitea-repositories-meta/user2/utf8.git/objects/a4/f1bb3f2f8c6a0e840e935812ef4903ce515dad new file mode 100644 index 0000000000000000000000000000000000000000..9655a74c8321a8c3d9cf08111c6f1b320bf641ba GIT binary patch literal 394 zcmV;50d@X(0V^p=O;s>4F<~$?FfcPQQBYMiGBq;I%}mcI$;&S($Vsd$PtD0;Na^hK zx+pOD?~yrtH^OhQHJNx7rNDF;nHsxg76Vl$7M7+Kmt^MW0nIRWV|bZdY~5uV^CRI% z>X!A@%2|0I+M8i|KsxLb^HP)((=u~X8GI7&a#habFnC^f|JiZ>8k5;4o@qgq8XBnT z<)$#S)Z|V+*2a6eJXOfGP`ZB4WiN>e(|)NKbT3+YLItYq o!jcOcF6_Lp8)VuSrvK>&HjBwvcHI6Z(U-^jDg19K0DZ-*LE@RcF8}}l literal 0 HcmV?d00001 diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/objects/c7/85b65bf16928b58567cb23669125c0ccd25a4f b/integrations/gitea-repositories-meta/user2/utf8.git/objects/c7/85b65bf16928b58567cb23669125c0ccd25a4f new file mode 100644 index 0000000000000000000000000000000000000000..2cc606b7f2630a7bfe9e14c3a2eb3df81e880e31 GIT binary patch literal 44 zcmV+{0Mq|?0ZYosPf{>8U`ELKR%%t=+q&&#P)$Ve;(GEx8WbiCe$SN%^QOGRLQ!i0SR46P>EiTE-&r`@vEXwBM0s#Gp F48*|e6Wjm* literal 0 HcmV?d00001 diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/refs/heads/Plus+Is+Not+Space b/integrations/gitea-repositories-meta/user2/utf8.git/refs/heads/Plus+Is+Not+Space index 00dd05db8c2a2..c2850d4c4d414 100644 --- a/integrations/gitea-repositories-meta/user2/utf8.git/refs/heads/Plus+Is+Not+Space +++ b/integrations/gitea-repositories-meta/user2/utf8.git/refs/heads/Plus+Is+Not+Space @@ -1 +1 @@ -3a810dbf6b96afaa8c5f69a8b6ec1dabfca7368b +59e2c41e8f5140bb0182acebec17c8ad9831cc62 diff --git a/integrations/nonascii_branches_test.go b/integrations/nonascii_branches_test.go index 22d71e6ee20e1..fe8434b5f5483 100644 --- a/integrations/nonascii_branches_test.go +++ b/integrations/nonascii_branches_test.go @@ -6,6 +6,7 @@ package integrations import ( "net/http" + "net/url" "path" "testing" @@ -159,6 +160,41 @@ func TestNonasciiBranches(t *testing.T) { to: "tag/%d0%81/%e4%ba%ba", status: http.StatusOK, }, + { + from: "Plus+Is+Not+Space/%25%252525mightnotplaywell", + to: "branch/Plus+Is+Not+Space/%25%252525mightnotplaywell", + status: http.StatusOK, + }, + { + from: "Plus+Is+Not+Space/%25253Fisnotaquestion%25253F", + to: "branch/Plus+Is+Not+Space/%25253Fisnotaquestion%25253F", + status: http.StatusOK, + }, + { + from: "Plus+Is+Not+Space/" + url.PathEscape("%3Fis?and#afile"), + to: "branch/Plus+Is+Not+Space/" + url.PathEscape("%3Fis?and#afile"), + status: http.StatusOK, + }, + { + from: "Plus+Is+Not+Space/10%25.md", + to: "branch/Plus+Is+Not+Space/10%25.md", + status: http.StatusOK, + }, + { + from: "Plus+Is+Not+Space/" + url.PathEscape("This+file%20has 1space"), + to: "branch/Plus+Is+Not+Space/" + url.PathEscape("This+file%20has 1space"), + status: http.StatusOK, + }, + { + from: "Plus+Is+Not+Space/" + url.PathEscape("This+file%2520has 2 spaces"), + to: "branch/Plus+Is+Not+Space/" + url.PathEscape("This+file%2520has 2 spaces"), + status: http.StatusOK, + }, + { + from: "Plus+Is+Not+Space/" + url.PathEscape("£15&$6.txt"), + to: "branch/Plus+Is+Not+Space/" + url.PathEscape("£15&$6.txt"), + status: http.StatusOK, + }, } defer prepareTestEnv(t)() diff --git a/modules/context/context.go b/modules/context/context.go index 568865d90e6c8..82771b0c244d5 100644 --- a/modules/context/context.go +++ b/modules/context/context.go @@ -669,6 +669,10 @@ func Contexter() func(next http.Handler) http.Handler { var locale = middleware.Locale(resp, req) var startTime = time.Now() var link = setting.AppSubURL + strings.TrimSuffix(req.URL.EscapedPath(), "/") + + chiCtx := chi.RouteContext(req.Context()) + chiCtx.RoutePath = req.URL.EscapedPath() + var ctx = Context{ Resp: NewResponse(resp), Cache: mc.GetCache(), From 84d5924cd9d0ac4fd8551ee163d63ca3bad81df4 Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Thu, 16 Dec 2021 19:30:43 +0000 Subject: [PATCH 2/3] escape redirect Signed-off-by: Andrew Thornton --- modules/context/repo.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/context/repo.go b/modules/context/repo.go index 12943ae37f818..0f78ff429b5d7 100644 --- a/modules/context/repo.go +++ b/modules/context/repo.go @@ -833,7 +833,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context setting.AppSubURL, strings.TrimSuffix(ctx.Req.URL.Path, ctx.Params("*")), ctx.Repo.BranchNameSubURL(), - ctx.Repo.TreePath)) + util.PathEscapeSegments(ctx.Repo.TreePath))) return } } From b049b72a1e53dfb590fd7a6f9e949a411a3257dd Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Thu, 16 Dec 2021 20:37:32 +0000 Subject: [PATCH 3/3] more test fixes Signed-off-by: Andrew Thornton --- integrations/nonascii_branches_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/integrations/nonascii_branches_test.go b/integrations/nonascii_branches_test.go index fe8434b5f5483..1aab16fa3e75a 100644 --- a/integrations/nonascii_branches_test.go +++ b/integrations/nonascii_branches_test.go @@ -84,7 +84,7 @@ func TestNonasciiBranches(t *testing.T) { }, { from: "Plus+Is+Not+Space/Файл.md", - to: "branch/Plus+Is+Not+Space/%d0%a4%d0%b0%d0%b9%d0%bb.md", + to: "branch/Plus+Is+Not+Space/%D0%A4%D0%B0%D0%B9%D0%BB.md", status: http.StatusOK, }, { @@ -115,7 +115,7 @@ func TestNonasciiBranches(t *testing.T) { }, { from: "タグ/ファイル.md", - to: "tag/%e3%82%bf%e3%82%b0/%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab.md", + to: "tag/%e3%82%bf%e3%82%b0/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB.md", status: http.StatusOK, }, // Files @@ -126,12 +126,12 @@ func TestNonasciiBranches(t *testing.T) { }, { from: "Файл.md", - to: "branch/Plus+Is+Not+Space/%d0%a4%d0%b0%d0%b9%d0%bb.md", + to: "branch/Plus+Is+Not+Space/%D0%A4%D0%B0%D0%B9%D0%BB.md", status: http.StatusOK, }, { from: "ファイル.md", - to: "branch/Plus+Is+Not+Space/%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab.md", + to: "branch/Plus+Is+Not+Space/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB.md", status: http.StatusNotFound, // it's not on default branch }, // Same but url-encoded (few tests) @@ -147,7 +147,7 @@ func TestNonasciiBranches(t *testing.T) { }, { from: "%D0%A4%D0%B0%D0%B9%D0%BB.md", - to: "branch/Plus+Is+Not+Space/%d0%a4%d0%b0%d0%b9%d0%bb.md", + to: "branch/Plus+Is+Not+Space/%D0%A4%D0%B0%D0%B9%D0%BB.md", status: http.StatusOK, }, {