[issue29110] [patch] Fix file object leak in `aifc.open` when given invalid AIFF file.

2017-02-18 Thread Anthony Zhang

Changes by Anthony Zhang <azha...@gmail.com>:


--
pull_requests: +127

___
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue29110>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue29110] [patch] Fix file object leak in `aifc.open` when given invalid AIFF file.

2016-12-29 Thread Anthony Zhang

Changes by Anthony Zhang <azha...@gmail.com>:


Added file: 
http://bugs.python.org/file46088/fix_aifc_leak_and_file_object_close.patch

___
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue29110>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue29110] [patch] Fix file object leak in `aifc.open` when given invalid AIFF file.

2016-12-29 Thread Anthony Zhang

New submission from Anthony Zhang:

Summary
---

This shows up as two closely-related issues:

* ``aifc.open`` leaks file object when invalid AIFF file encountered. This is 
probably a bug.
* ``aifc.close`` closes file object even when it didn't open the file object to 
begin with. While this is technically documented behaviour [1], it's 
inconsistent with how similar modules like ``wave`` work [2].

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 
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:

* The first patch, "fix_aifc_leak.patch", makes no functionality changes, so 
there shouldn't be any backwards compatibility concerns.
* The second patch, "fix_aifc_leak_and_file_object_close.patch", slightly 
changes the behaviour of `aifc_instance.close()` so that it closes in only a 
subset of cases it would originally. While it is possible for this to lead to 
leaks in certain cases (example below), the impact shoul be low, as existing 
codebases seem to use context managers and similar constructs that clean 
everything up properly.

#!/usr/bin/env python3

from os import path
FILE = path.expanduser("~/cpython/Lib/test/audiodata/pluck-pcm8.aiff")
import aifc
f = open(FILE, "rb")
with aifc.open(f, "rb"):
pass
# with the patch applied, `f` is not closed at this point anymore

[1]: https://docs.python.org/3/library/aifc.html#aifc.aifc.close
[2]: https://docs.python.org/3/library/wave.html#wave.Wave_read.close

--
components: Library (Lib)
files: fix_aifc_leak.patch
keywords: patch
messages: 284299
nosy: azhang
priority: normal
severity: normal
status: open
title: [patch] Fix file object leak in `aifc.open` when given invalid AIFF file.
type: behavior
versions: Python 2.7, Python 3.3, Python 3.4, Python 3.5, Python 3.6, Python 3.7
Added file: http://bugs.python.org/file46087/fix_aifc_leak.patch

___
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue29110>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com