Jens Geyer created THRIFT-6232:
----------------------------------
Summary: Twisted SASL client protocol raises TypeError on Python 3
(mixes str and bytes)
Key: THRIFT-6232
URL: https://issues.apache.org/jira/browse/THRIFT-6232
Project: Thrift
Issue Type: Bug
Components: Python - Library
Reporter: Jens Geyer
{{ThriftSASLClientProtocol}} in {{lib/py/src/transport/TTwisted.py}} does not
run on Python 3: three of its methods build a message by mixing {{str}} and
{{bytes}}, or index a {{bytes}} object for an {{int}}, and raise {{TypeError}}.
The library is Python 3 only ({{setup.py}} lists only {{Programming Language ::
Python :: 3}}), so the SASL-over-Twisted client cannot complete a negotiation
or send a call. The code has been this way since it was added for Python 2 in
THRIFT-1719 (2014).
Reproduced against master with a minimal SASL stand-in whose {{wrap()}} returns
{{bytes}}, as a real {{puresasl}} client does:
* {{dispatch(msg)}} -- the send path for every SASL-wrapped call:
{code:python}
len_and_encoded = ''.join((struct.pack('!i', len(encoded)), encoded))
{code}
{{''.join}} over a {{str}} and a {{bytes}} raises {{TypeError: sequence item 0:
expected str instance, bytes found}}.
* {{_sendSASLMessage(status, body)}} -- {{connectionMade}} calls it first with
{{self.sasl.mechanism}}, a {{str}}:
{code:python}
header = struct.pack(">BI", status, len(body))
self.transport.write(header + body)
{code}
{{header}} is {{bytes}}, {{body}} is a {{str}}, so {{header + body}} raises
{{TypeError: can't concat str to bytes}}.
* {{dataReceived(data)}} during SASL negotiation:
{code:python}
self._sasl_negotiation_status, = struct.unpack("B", data[0])
{code}
{{data[0]}} is an {{int}} on Python 3, and {{struct.unpack}} wants a buffer, so
this raises {{TypeError: a bytes-like object is required, not 'int'}} -- it
needs {{data[0:1]}}.
Two more spots on the same paths read as Python-2-only and would surface once
the above are fixed: {{ThriftSASLClientProtocol.__init__}} keeps the class as
{{self.SASLCLient}} (note the capitalisation) and then {{createSASLClient}}
calls {{self.SASLClient(...)}}, which does not exist; and {{_sendSASLMessage}}
encodes a {{str}} body without a call to {{.encode()}}.
A fix should build these messages as {{bytes}} throughout and slice rather than
index, and would want a test. The Twisted SASL client is currently not
exercised by the test suite ({{puresasl}} is an optional dependency), which is
why this has gone unnoticed.
This is a functional defect, not a change to on-the-wire behaviour or security
posture.
_Drafted with AI assistance (Claude Opus 5); reviewed and filed by Jens Geyer._
--
This message was sent by Atlassian Jira
(v8.20.10#820010)