Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RecursionError in email.utils.parseaddr #103800

Closed
baltsers opened this issue Apr 24, 2023 · 2 comments
Closed

RecursionError in email.utils.parseaddr #103800

baltsers opened this issue Apr 24, 2023 · 2 comments

Comments

@baltsers
Copy link

baltsers commented Apr 24, 2023

Bug report

We did a fuzzing test on Python3.9.15, a recursion error happened.

from email.utils import *
import email
import email.utils
import re

class demoCls():

    def __init__(self):
        pass

    def demoFunc(self, arg):
        try:
            ret = email.utils.parseaddr(arg)
        except (AttributeError, LookupError, OSError, TypeError, UnicodeEncodeError, ValueError):
            pass

with open("data.txt","r") as f:
    addr = f.readline()
    dc = demoCls()
    dc.demoFunc(addr)

code

The input value:

%usel�ayQ�WexQeGM4R:::::::::::::::::::::::::::::set::::::::::::::::::::::::::::::::::�::::::::::::�_threshold2qR)phqzE7C4::::::::::::::::::::E7C4:::::::::::::::::::::::::::::set::::::::::::::::::::::::::::::::::�::::::::::::::::::::::::::::::set::::::::::::::::::::::::::::::::::�::::::::::::�_threshold2qR)phqzE7C4::::::::::::::::::::E7C4:::::::::::::::::::::::::::::set::::::::::::::::::::::::::::::::::�::::::::::::::::::::::::::::::set::::::::::::::::::::::::::::::::::�::::::::::::�_threshold2qR)phqzE7C4:::::::::::::::::::::::::::::set::::::::::::::::::::::::::::::::::�::::::::::::�_threshold2qR)phqzE7C4::::::::::::::::::::E7C4:::::::::::::::::::::::::::::set::::::::::::::::::::::::::::::::::�::::::::::::::::::::::::::::::set::::::::::::::::::::::::::::::::::�::::::::::::�_threshold2qR)phqzE7C4::::::::::::::::::::E7C4:::::::::::::::::::::::::::::set:::::::::::::::::::::�����:::::::::::::�:::::::::::::::::::::::::::::::::::::::::set::::::::::::::::::::::::::::::::::�::::::::::::�_threshold2qR)phqzE7C4::::::::::::::::::::E7C4:::::::::::::::::::::::::::::set::::::::::::::::::::::::::::::::::�::::::::::::::::::::::::::::::set::::::::::::::::::::::::::::::::::�::::::::::::�_threshold2qR)phqzE7C4::::::::::::::::::::E7C4:::::::::::::::::::::::::::::set:::::::::::::::::::::�����:::::::::::::�::::::::::::::::::::::::::::::::E7C4:::::::::::::::::::::::::::::set:::::::::::::::::::::�����:::::::::::::�::::::::::::�_threshold2qR)phqz

input

Bug info

Traceback (most recent call last):
  File "/root/fuzzVuls/Python3.9.15/email.utils.parseaddr/1#email#utils#parseaddr.py", line 20, in <module>
    dc.demoFunc(addr)
  File "/root/fuzzVuls/Python3.9.15/email.utils.parseaddr/1#email#utils#parseaddr.py", line 13, in demoFunc
    ret = email.utils.parseaddr(arg)
  File "/root/anaconda3/lib/python3.9/email/utils.py", line 212, in parseaddr
    addrs = _AddressList(addr).addresslist
  File "/root/anaconda3/lib/python3.9/email/_parseaddr.py", line 513, in __init__
    self.addresslist = self.getaddrlist()
  File "/root/anaconda3/lib/python3.9/email/_parseaddr.py", line 257, in getaddrlist
    ad = self.getaddress()
  File "/root/anaconda3/lib/python3.9/email/_parseaddr.py", line 300, in getaddress
    returnlist = returnlist + self.getaddress()
  File "/root/anaconda3/lib/python3.9/email/_parseaddr.py", line 300, in getaddress
    returnlist = returnlist + self.getaddress()
  File "/root/anaconda3/lib/python3.9/email/_parseaddr.py", line 300, in getaddress
    returnlist = returnlist + self.getaddress()
  [Previous line repeated 989 more times]
  File "/root/anaconda3/lib/python3.9/email/_parseaddr.py", line 267, in getaddress
    self.gotonext()
  File "/root/anaconda3/lib/python3.9/email/_parseaddr.py", line 239, in gotonext
    while self.pos < len(self.field):
RecursionError: maximum recursion depth exceeded while calling a Python object

My environment

CPython: 3.9.15
Ubuntu: 18.0.4 (x86 64)

@baltsers baltsers added the type-bug An unexpected behavior, bug, or error label Apr 24, 2023
@zware
Copy link
Member

zware commented Apr 24, 2023

Can you explain why this is a problem that needs to be fixed? If you give pathological input to a function, an exception is not an unexpected result.

Also note that this can be reproduced with just the following:

from email.utils import parseaddr
parseaddr(':' * 100_000)

Please put some effort into reducing your reproducers to the smallest possible code before posting an issue.

@zware zware added the pending The issue will be closed if no feedback is provided label Apr 24, 2023
@terryjreedy
Copy link
Member

terryjreedy commented Apr 25, 2023

The RecursionError is not a bug when the (modifiable) recursion limit is reached. Nor is using recursion in our code, given that we have documented that our code has (undocumented) input size limits. So, not a bug.

There could possibly be a performance feaure request. returnlist = returnlist + self.getaddress() is the only direct recursion in getaddress. It is triggered by ':'. If there are no indirectly recursive calls, getaddress could be made tail recursive and thence iterative. (But not quite trivially.) However, given that parseaddr(':' * n) is ('', '') for n up to 1022 (on my machine in IDLE with default sys, 1023 raises RecursionError), I suspect that the default stack limit is sufficient for nearly all uses of Python's email module. If not, one can raise the stacklimit in code.

EDIT: replace incorrect statement and misleading example with corrected statement.

@terryjreedy terryjreedy removed the type-bug An unexpected behavior, bug, or error label Apr 25, 2023
@zware zware closed this as not planned Won't fix, can't repro, duplicate, stale Apr 25, 2023
@zware zware removed the pending The issue will be closed if no feedback is provided label Apr 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants