Do not use canonicaljson to magically handle decoding bytes from JSON. (#7802)

This commit is contained in:
Patrick Cloke 2020-07-10 14:30:08 -04:00 committed by GitHub
parent d9e47af617
commit 66a4af8d96
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 17 additions and 28 deletions

1
changelog.d/7802.misc Normal file
View file

@ -0,0 +1 @@
Switch from simplejson to the standard library json.

View file

@ -15,13 +15,11 @@
# limitations under the License. # limitations under the License.
"""Contains exceptions and error codes.""" """Contains exceptions and error codes."""
import json
import logging import logging
from http import HTTPStatus from http import HTTPStatus
from typing import Dict, List from typing import Dict, List
from canonicaljson import json
from twisted.web import http from twisted.web import http
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -573,7 +571,7 @@ class HttpResponseException(CodeMessageException):
# try to parse the body as json, to get better errcode/msg, but # try to parse the body as json, to get better errcode/msg, but
# default to M_UNKNOWN with the HTTP status as the error text # default to M_UNKNOWN with the HTTP status as the error text
try: try:
j = json.loads(self.response) j = json.loads(self.response.decode("utf-8"))
except ValueError: except ValueError:
j = {} j = {}

View file

@ -14,10 +14,10 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import json
import logging import logging
from typing import Any, Callable, Dict, List, Match, Optional, Tuple, Union from typing import Any, Callable, Dict, List, Match, Optional, Tuple, Union
from canonicaljson import json
from prometheus_client import Counter, Histogram from prometheus_client import Counter, Histogram
from twisted.internet import defer from twisted.internet import defer
@ -526,9 +526,9 @@ class FederationServer(FederationBase):
json_result = {} # type: Dict[str, Dict[str, dict]] json_result = {} # type: Dict[str, Dict[str, dict]]
for user_id, device_keys in results.items(): for user_id, device_keys in results.items():
for device_id, keys in device_keys.items(): for device_id, keys in device_keys.items():
for key_id, json_bytes in keys.items(): for key_id, json_str in keys.items():
json_result.setdefault(user_id, {})[device_id] = { json_result.setdefault(user_id, {})[device_id] = {
key_id: json.loads(json_bytes) key_id: json.loads(json_str)
} }
logger.info( logger.info(

View file

@ -104,7 +104,7 @@ class CasHandler:
return user, displayname return user, displayname
def _parse_cas_response( def _parse_cas_response(
self, cas_response_body: str self, cas_response_body: bytes
) -> Tuple[str, Dict[str, Optional[str]]]: ) -> Tuple[str, Dict[str, Optional[str]]]:
""" """
Retrieve the user and other parameters from the CAS response. Retrieve the user and other parameters from the CAS response.

View file

@ -13,13 +13,13 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import json
import logging import logging
import urllib import urllib
from io import BytesIO from io import BytesIO
import treq import treq
from canonicaljson import encode_canonical_json, json from canonicaljson import encode_canonical_json
from netaddr import IPAddress from netaddr import IPAddress
from prometheus_client import Counter from prometheus_client import Counter
from zope.interface import implementer, provider from zope.interface import implementer, provider
@ -371,7 +371,7 @@ class SimpleHttpClient(object):
body = yield make_deferred_yieldable(readBody(response)) body = yield make_deferred_yieldable(readBody(response))
if 200 <= response.code < 300: if 200 <= response.code < 300:
return json.loads(body) return json.loads(body.decode("utf-8"))
else: else:
raise HttpResponseException(response.code, response.phrase, body) raise HttpResponseException(response.code, response.phrase, body)
@ -412,7 +412,7 @@ class SimpleHttpClient(object):
body = yield make_deferred_yieldable(readBody(response)) body = yield make_deferred_yieldable(readBody(response))
if 200 <= response.code < 300: if 200 <= response.code < 300:
return json.loads(body) return json.loads(body.decode("utf-8"))
else: else:
raise HttpResponseException(response.code, response.phrase, body) raise HttpResponseException(response.code, response.phrase, body)
@ -441,7 +441,7 @@ class SimpleHttpClient(object):
actual_headers.update(headers) actual_headers.update(headers)
body = yield self.get_raw(uri, args, headers=headers) body = yield self.get_raw(uri, args, headers=headers)
return json.loads(body) return json.loads(body.decode("utf-8"))
@defer.inlineCallbacks @defer.inlineCallbacks
def put_json(self, uri, json_body, args={}, headers=None): def put_json(self, uri, json_body, args={}, headers=None):
@ -485,7 +485,7 @@ class SimpleHttpClient(object):
body = yield make_deferred_yieldable(readBody(response)) body = yield make_deferred_yieldable(readBody(response))
if 200 <= response.code < 300: if 200 <= response.code < 300:
return json.loads(body) return json.loads(body.decode("utf-8"))
else: else:
raise HttpResponseException(response.code, response.phrase, body) raise HttpResponseException(response.code, response.phrase, body)
@ -503,7 +503,7 @@ class SimpleHttpClient(object):
header name to a list of values for that header header name to a list of values for that header
Returns: Returns:
Deferred: Succeeds when we get *any* 2xx HTTP response, with the Deferred: Succeeds when we get *any* 2xx HTTP response, with the
HTTP body at text. HTTP body as bytes.
Raises: Raises:
HttpResponseException on a non-2xx HTTP response. HttpResponseException on a non-2xx HTTP response.
""" """

View file

@ -14,11 +14,9 @@
# limitations under the License. # limitations under the License.
""" This module contains base REST classes for constructing REST servlets. """ """ This module contains base REST classes for constructing REST servlets. """
import json
import logging import logging
from canonicaljson import json
from synapse.api.errors import Codes, SynapseError from synapse.api.errors import Codes, SynapseError
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -214,16 +212,8 @@ def parse_json_value_from_request(request, allow_empty_body=False):
if not content_bytes and allow_empty_body: if not content_bytes and allow_empty_body:
return None return None
# Decode to Unicode so that simplejson will return Unicode strings on
# Python 2
try: try:
content_unicode = content_bytes.decode("utf8") content = json.loads(content_bytes.decode("utf-8"))
except UnicodeDecodeError:
logger.warning("Unable to decode UTF-8")
raise SynapseError(400, "Content not JSON.", errcode=Codes.NOT_JSON)
try:
content = json.loads(content_unicode)
except Exception as e: except Exception as e:
logger.warning("Unable to parse JSON: %s", e) logger.warning("Unable to parse JSON: %s", e)
raise SynapseError(400, "Content not JSON.", errcode=Codes.NOT_JSON) raise SynapseError(400, "Content not JSON.", errcode=Codes.NOT_JSON)

View file

@ -398,7 +398,7 @@ class CASTestCase(unittest.HomeserverTestCase):
</cas:serviceResponse> </cas:serviceResponse>
""" """
% cas_user_id % cas_user_id
) ).encode("utf-8")
mocked_http_client = Mock(spec=["get_raw"]) mocked_http_client = Mock(spec=["get_raw"])
mocked_http_client.get_raw.side_effect = get_raw mocked_http_client.get_raw.side_effect = get_raw