[Bug 1915819] [NEW] 'NoneType' object has no attribute 'encode' in requestReceived() when multipart body doesn't include content-disposition
Victor Tapia
1915819 at bugs.launchpad.net
Tue Feb 16 12:54:42 UTC 2021
Public bug reported:
[impact]
python-twisted errors out with "'NoneType' object has no attribute
'encode' in requestReceived()" when it tries to parse a multipart mime
message and python3.7+ is used. This happens because before commit
cc3fa20 in cpython, cgi.parse_multipart ignored parts without a name
defined in "content-disposition" (or parts without headers for that
matter) but after 3.7+ the return of the function can now contain
NoneType keys, which fail to encode.
[scope]
This bug affects all releases
Fixed upstream with commit 310496249, available since 21.2.0rc1
[test case]
1. Save the following code as webserver.py
from twisted.application.internet import TCPServer
from twisted.application.service import Application
from twisted.web.resource import Resource
from twisted.web.server import Site
class Foo(Resource):
def render_POST(self, request):
newdata = request.content.getvalue()
print(newdata)
return ''
root = Resource()
root.putChild("foo", Foo())
application = Application("cgi.parse_multipart test")
TCPServer(8080, Site(root)).setServiceParent(application)
2. Save the following code as client.py (python3-httplib2 is required)
#!/usr/bin/env python
import httplib2
def http_request(url, method, body=None, headers=None, insecure=False):
"""Issue an http request."""
http = httplib2.Http(disable_ssl_certificate_validation=insecure)
if isinstance(url, bytes):
url = url.decode("ascii")
return http.request(url, method, body=body, headers=headers)
url = "http://localhost:8080"
method = "POST"
headers = {'Content-Type': 'multipart/form-data; boundary="8825899812428059282"'}
emptyh = '--8825899812428059282\n\n--8825899812428059282--'
print("== BODY: " + emptyh + "\n")
response, content = http_request(url, method, emptyh, headers)
3. Run the server with "twistd3 -y webserver.py"
4. Run the client
5. twistd will fail to encode the key and will drop this traceback in the log file (twistd.log)
2021-02-16T13:41:39+0100 [_GenericHTTPChannelProtocol,7,127.0.0.1] Unhandled Error
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/twisted/python/log.py", line 103, in callWithLogger
return callWithContext({"system": lp}, func, *args, **kw)
File "/usr/lib/python3/dist-packages/twisted/python/log.py", line 86, in callWithContext
return context.call({ILogContext: newCtx}, func, *args, **kw)
File "/usr/lib/python3/dist-packages/twisted/python/context.py", line 122, in callWithContext
return self.currentContext().callWithContext(ctx, func, *args, **kw)
File "/usr/lib/python3/dist-packages/twisted/python/context.py", line 85, in callWithContext
return func(*args,**kw)
--- <exception caught here> ---
File "/usr/lib/python3/dist-packages/twisted/internet/posixbase.py", line 614, in _doReadOrWrite
why = selectable.doRead()
File "/usr/lib/python3/dist-packages/twisted/internet/tcp.py", line 243, in doRead
return self._dataReceived(data)
File "/usr/lib/python3/dist-packages/twisted/internet/tcp.py", line 249, in _dataReceived
rval = self.protocol.dataReceived(data)
File "/usr/lib/python3/dist-packages/twisted/web/http.py", line 2952, in dataReceived
return self._channel.dataReceived(data)
File "/usr/lib/python3/dist-packages/twisted/web/http.py", line 2245, in dataReceived
return basic.LineReceiver.dataReceived(self, data)
File "/usr/lib/python3/dist-packages/twisted/protocols/basic.py", line 579, in dataReceived
why = self.rawDataReceived(data)
File "/usr/lib/python3/dist-packages/twisted/web/http.py", line 2252, in rawDataReceived
self._transferDecoder.dataReceived(data)
File "/usr/lib/python3/dist-packages/twisted/web/http.py", line 1699, in dataReceived
finishCallback(data[contentLength:])
File "/usr/lib/python3/dist-packages/twisted/web/http.py", line 2115, in _finishRequestBody
self.allContentReceived()
File "/usr/lib/python3/dist-packages/twisted/web/http.py", line 2224, in allContentReceived
req.requestReceived(command, path, version)
File "/usr/lib/python3/dist-packages/twisted/web/http.py", line 898, in requestReceived
self.args.update({
File "/usr/lib/python3/dist-packages/twisted/web/http.py", line 899, in <dictcomp>
x.encode('iso-8859-1'): \
builtins.AttributeError: 'NoneType' object has no attribute 'encode'
[regression potential]
This affects the returned dictionaries with non-str keys, which were
discarded in python3.6 or earlier before they reached twisted, so
patching this will make its behavior consistent.
** Affects: twisted (Ubuntu)
Importance: Undecided
Status: New
** Tags: sts
--
You received this bug notification because you are a member of Ubuntu
Foundations Bugs, which is subscribed to twisted in Ubuntu.
https://bugs.launchpad.net/bugs/1915819
Title:
'NoneType' object has no attribute 'encode' in requestReceived() when
multipart body doesn't include content-disposition
Status in twisted package in Ubuntu:
New
Bug description:
[impact]
python-twisted errors out with "'NoneType' object has no attribute
'encode' in requestReceived()" when it tries to parse a multipart mime
message and python3.7+ is used. This happens because before commit
cc3fa20 in cpython, cgi.parse_multipart ignored parts without a name
defined in "content-disposition" (or parts without headers for that
matter) but after 3.7+ the return of the function can now contain
NoneType keys, which fail to encode.
[scope]
This bug affects all releases
Fixed upstream with commit 310496249, available since 21.2.0rc1
[test case]
1. Save the following code as webserver.py
from twisted.application.internet import TCPServer
from twisted.application.service import Application
from twisted.web.resource import Resource
from twisted.web.server import Site
class Foo(Resource):
def render_POST(self, request):
newdata = request.content.getvalue()
print(newdata)
return ''
root = Resource()
root.putChild("foo", Foo())
application = Application("cgi.parse_multipart test")
TCPServer(8080, Site(root)).setServiceParent(application)
2. Save the following code as client.py (python3-httplib2 is required)
#!/usr/bin/env python
import httplib2
def http_request(url, method, body=None, headers=None, insecure=False):
"""Issue an http request."""
http = httplib2.Http(disable_ssl_certificate_validation=insecure)
if isinstance(url, bytes):
url = url.decode("ascii")
return http.request(url, method, body=body, headers=headers)
url = "http://localhost:8080"
method = "POST"
headers = {'Content-Type': 'multipart/form-data; boundary="8825899812428059282"'}
emptyh = '--8825899812428059282\n\n--8825899812428059282--'
print("== BODY: " + emptyh + "\n")
response, content = http_request(url, method, emptyh, headers)
3. Run the server with "twistd3 -y webserver.py"
4. Run the client
5. twistd will fail to encode the key and will drop this traceback in the log file (twistd.log)
2021-02-16T13:41:39+0100 [_GenericHTTPChannelProtocol,7,127.0.0.1] Unhandled Error
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/twisted/python/log.py", line 103, in callWithLogger
return callWithContext({"system": lp}, func, *args, **kw)
File "/usr/lib/python3/dist-packages/twisted/python/log.py", line 86, in callWithContext
return context.call({ILogContext: newCtx}, func, *args, **kw)
File "/usr/lib/python3/dist-packages/twisted/python/context.py", line 122, in callWithContext
return self.currentContext().callWithContext(ctx, func, *args, **kw)
File "/usr/lib/python3/dist-packages/twisted/python/context.py", line 85, in callWithContext
return func(*args,**kw)
--- <exception caught here> ---
File "/usr/lib/python3/dist-packages/twisted/internet/posixbase.py", line 614, in _doReadOrWrite
why = selectable.doRead()
File "/usr/lib/python3/dist-packages/twisted/internet/tcp.py", line 243, in doRead
return self._dataReceived(data)
File "/usr/lib/python3/dist-packages/twisted/internet/tcp.py", line 249, in _dataReceived
rval = self.protocol.dataReceived(data)
File "/usr/lib/python3/dist-packages/twisted/web/http.py", line 2952, in dataReceived
return self._channel.dataReceived(data)
File "/usr/lib/python3/dist-packages/twisted/web/http.py", line 2245, in dataReceived
return basic.LineReceiver.dataReceived(self, data)
File "/usr/lib/python3/dist-packages/twisted/protocols/basic.py", line 579, in dataReceived
why = self.rawDataReceived(data)
File "/usr/lib/python3/dist-packages/twisted/web/http.py", line 2252, in rawDataReceived
self._transferDecoder.dataReceived(data)
File "/usr/lib/python3/dist-packages/twisted/web/http.py", line 1699, in dataReceived
finishCallback(data[contentLength:])
File "/usr/lib/python3/dist-packages/twisted/web/http.py", line 2115, in _finishRequestBody
self.allContentReceived()
File "/usr/lib/python3/dist-packages/twisted/web/http.py", line 2224, in allContentReceived
req.requestReceived(command, path, version)
File "/usr/lib/python3/dist-packages/twisted/web/http.py", line 898, in requestReceived
self.args.update({
File "/usr/lib/python3/dist-packages/twisted/web/http.py", line 899, in <dictcomp>
x.encode('iso-8859-1'): \
builtins.AttributeError: 'NoneType' object has no attribute 'encode'
[regression potential]
This affects the returned dictionaries with non-str keys, which were
discarded in python3.6 or earlier before they reached twisted, so
patching this will make its behavior consistent.
To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/twisted/+bug/1915819/+subscriptions
More information about the foundations-bugs
mailing list