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)

Reply via email to