Issue 29110: [patch] Fix file object leak in aifc.open when given invalid AIFF file. (original) (raw)

Summary

This shows up as two closely-related issues:

I have confirmed the issue is present in all the selected Python versions.

Steps to reproduce

For the first issue, run this code:

#!/usr/bin/env python3

# to simplify this example, use this script itself as a random non-AIFF file (though any non-AIFF file will work fine)
FILE = __file__

# print warnings on stderr
import warnings
warnings.resetwarnings()

# try to open the non-AIFF file as an AIFF file, which should fail, but shouldn't give any ResourceWarnings
import aifc
try: aifc.open(FILE, "rb")
except: pass

For the second issue, run this code:

#!/usr/bin/env python3

from os import path
FILE = path.expanduser("~/cpython/Lib/test/audiodata/pluck-pcm8.aiff")

# open the file as a file-like object, then open it again with ``aifc.open``
import aifc
with open(FILE, "rb") as f:
    assert not f.closed, "Before opening with AIFC"
    with aifc.open(f, "rb"):
        pass
    assert not f.closed, "After opening with AIFC"

Expected result

For the first code sample, code should give no output - aifc.open should throw an exception due to the passed filename being an invalid AIFF file, but that exception should be caught and suppressed. by the try/except statements.

For the second code sample, all assertions should pass - the file should be opened with open, "opened" again with aifc.open, and should not be closed when the inner context manager exits.

Actual result

For the first code sample:

$ python3 test.py
/home/anthony/Desktop/test.py:13: ResourceWarning: unclosed file <_io.BufferedReader name='/home/anthony/Desktop/test.py'>
  except: pass

In other words, code executes as described in "Expected result", but also prints a warning to stderr about the file object not being closed.

For the second code sample:

$ python3 "/home/anthony/Desktop/test.py"
Traceback (most recent call last):
  File "/home/anthony/Desktop/test.py", line 11, in <module>
    assert not f.closed, "After opening with AIFC"
AssertionError: After opening with AIFC

In other words, code runs normally until the inner context manager exits, and the file object gets closed, even though the file object wasn't opened by aifc.

Solution

Attached are patches that fix each issue separately - the first patch fixes the first mentioned issue, while the second patch fixes both at once.

Backwards compatibility: