Patchwork D2738: hgweb: only recognize wire protocol commands from query string (BC)

login
register
mail settings
Submitter phabricator
Date March 9, 2018, 1:06 a.m.
Message ID <differential-rev-PHID-DREV-oqksjykalqjbe6c3py5e-req@phab.mercurial-scm.org>
Download mbox | patch
Permalink /patch/29145/
State Superseded
Headers show

Comments

phabricator - March 9, 2018, 1:06 a.m.
indygreg created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  Previously, we attempted to parse the wire protocol command from
  `req.form`. Data could have come from the query string or POST
  form data.
  
  The wire protocol states that the command must be declared in the
  query string. And AFAICT all Mercurial releases from at least 1.0
  send the command in the query string.
  
  So let's actual require this behavior.
  
  This is technically BC. But I'm not sure how anyone in the wild
  would encounter this. POST has historically been used for sending
  bundle data. So there's no opportunity to encode arguments there.
  And the experimental HTTP POST args also takes over the body. So
  the only way someone would be impacted by this is if they wrote
  a custom client that both used POST for everything and sent arguments
  via the HTTP body. I don't believe such a client exists.
  
  .. bc::
  
    The HTTP wire protocol server no longer accepts the ``cmd``
    argument to control which command to run via HTTP POST bodies.
    The ``cmd`` argument must be specified on the URL query string.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D2738

AFFECTED FILES
  mercurial/hgweb/hgweb_mod.py
  mercurial/wireprotoserver.py

CHANGE DETAILS




To: indygreg, #hg-reviewers
Cc: mercurial-devel

Patch

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -150,25 +150,26 @@ 
 def iscmd(cmd):
     return cmd in wireproto.commands
 
-def parsehttprequest(rctx, wsgireq, query, checkperm):
+def parsehttprequest(rctx, wsgireq, req, checkperm):
     """Parse the HTTP request for a wire protocol request.
 
     If the current request appears to be a wire protocol request, this
     function returns a dict with details about that request, including
     an ``abstractprotocolserver`` instance suitable for handling the
     request. Otherwise, ``None`` is returned.
 
     ``wsgireq`` is a ``wsgirequest`` instance.
+    ``req`` is a ``parsedrequest`` instance.
     """
     repo = rctx.repo
 
     # HTTP version 1 wire protocol requests are denoted by a "cmd" query
     # string parameter. If it isn't present, this isn't a wire protocol
     # request.
-    if 'cmd' not in wsgireq.form:
+    if 'cmd' not in req.querystringdict:
         return None
 
-    cmd = wsgireq.form['cmd'][0]
+    cmd = req.querystringdict['cmd'][0]
 
     # The "cmd" request parameter is used by both the wire protocol and hgweb.
     # While not all wire protocol commands are available for all transports,
diff --git a/mercurial/hgweb/hgweb_mod.py b/mercurial/hgweb/hgweb_mod.py
--- a/mercurial/hgweb/hgweb_mod.py
+++ b/mercurial/hgweb/hgweb_mod.py
@@ -330,7 +330,7 @@ 
 
         # Route it to a wire protocol handler if it looks like a wire protocol
         # request.
-        protohandler = wireprotoserver.parsehttprequest(rctx, wsgireq, query,
+        protohandler = wireprotoserver.parsehttprequest(rctx, wsgireq, req,
                                                         self.check_perm)
 
         if protohandler: