Skip to content

bpo-44687: Fix unintended closing file error when peeking a BufferedReader object #28457

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

Merged

Conversation

AngstyDuck
Copy link
Contributor

@AngstyDuck AngstyDuck commented Sep 19, 2021

When the user runs the peek() function twice on a BufferedReader object, a closed file error may unintentionally be raised on the second time. This PR applies a check specific to the peek() function which runs only when the previous file operation is a peek().

https://bugs.python.org/issue44687

@liquidpele
Copy link

What about a read() after the first peek too? I’d expect peek() to allow a read afterward.

@AngstyDuck
Copy link
Contributor Author

Thanks for pointing it out, I'll alter the fix to accommodate the order you've mentioned as well.

@@ -0,0 +1 @@
Add a new :c:macro:`PEEK_CHECK_CLOSED` macro to check if a file is closed using a method specific to BufferedReader.peek()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The NEWS entry should be relevant to users, not developers. This would be a better commit message, while the PR title would be better for NEWS.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the feedback, i've updated the NEWS entry to incorporate more of the PR title. Hope that works 👍

CHECK_CLOSED(self, "peek of closed file")

// use a check specific to peek if the previous file operation was not a read
if (Py_SAFE_DOWNCAST(self->pos, Py_off_t, Py_ssize_t) == 0) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I'm reading this correctly, this just means we haven't done a read or a seek yet?

Wouldn't it be better to not close the file after a peek, but wait for the read? If the read never comes, it'll be closed when the stream is closed as it normally would.

Copy link
Contributor Author

@AngstyDuck AngstyDuck Sep 24, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I'm reading this correctly, this just means we haven't done a read or a seek yet?

thanks for your comment, and yes the if condition checks if a read or a seek has been done before.

Wouldn't it be better to not close the file after a peek, but wait for the read? If the read never comes, it'll be closed when the stream is closed as it normally would.

I considered this solution initially as well, but unfortunately based on the example provided, the closing of the file is actually done by one of the methods of the object that requests.get("https://amazon.com", stream=True).raw returns.

I've just pushed an alternate fix, where I've reset some attributes of BufferedReader when its method closed() has been called. I believe this fixes the bug while passing the test case I've previously encountered which prompted me to write this i condition in the first place. Do let me know what you think.

…new check now works regardless of which method was called before peek()
…thub.com:AngstyDuck/cpython into iobuffreader_stop_closing_file_error_during_peek
@AngstyDuck
Copy link
Contributor Author

After digging into the issue further, I've realised that the bug can be seen for all methods that use the original check CHECK_CLOSED. The latest commit not only replaces the old check entirely with the new one, but also fixes the issue in a way where any methods (read/seek/peek) can be called before the peek() in question. Do let me know what you think 👍

…7.3fqDRC.rst

Co-authored-by: Steve Dower <steve.dower@microsoft.com>
@AngstyDuck AngstyDuck requested a review from zooba September 30, 2021 10:42
@zooba zooba added needs backport to 3.9 only security fixes needs backport to 3.10 only security fixes labels Oct 1, 2021
@zooba zooba merged commit a450398 into python:main Oct 1, 2021
@miss-islington
Copy link
Contributor

Thanks @AngstyDuck for the PR, and @zooba for merging it 🌮🎉.. I'm working now to backport this PR to: 3.9, 3.10.
🐍🍒⛏🤖

@bedevere-bot
Copy link

GH-28685 is a backport of this pull request to the 3.10 branch.

@bedevere-bot bedevere-bot removed the needs backport to 3.9 only security fixes label Oct 1, 2021
@bedevere-bot
Copy link

GH-28686 is a backport of this pull request to the 3.9 branch.

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Oct 1, 2021
… even when the underlying file is closed (pythonGH-28457)

(cherry picked from commit a450398)

Co-authored-by: AngstyDuck <solsticedante@gmail.com>
miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Oct 1, 2021
… even when the underlying file is closed (pythonGH-28457)

(cherry picked from commit a450398)

Co-authored-by: AngstyDuck <solsticedante@gmail.com>
miss-islington added a commit that referenced this pull request Oct 1, 2021
… even when the underlying file is closed (GH-28457)

(cherry picked from commit a450398)

Co-authored-by: AngstyDuck <solsticedante@gmail.com>
zooba pushed a commit that referenced this pull request Oct 1, 2021
… even when the underlying file is closed (GH-28457)

Co-authored-by: AngstyDuck <solsticedante@gmail.com>
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

Successfully merging this pull request may close these issues.

6 participants