[proxy] web.archive.org← back | site home | direct (HTTPS) ↗ | proxy home | ◑ dark◐ light

/ cpython Public

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

bpo-35993: Fix an incorrect use of released memory #11852

Merged
merged 8 commits into from Feb 20, 2019

Conversation

Copy link
Member

matrixise commented Feb 14, 2019

Python/pystate.c Outdated
@@ -293,7 +294,8 @@ _PyInterpreterState_DeleteExceptMain()
if (interp->id_mutex != NULL) {
PyThread_free_lock(interp->id_mutex);
}
PyMem_RawFree(interp);
tmp_interp = interp;
PyMem_RawFree(tmp_interp);
Copy link
Member

vstinner Feb 14, 2019

Choose a reason for hiding this comment

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

I don't understand how the current code can work since PyMem_RawFree() fills freed memory with a byte pattern 0xDB and so interp = interp->next should just crash.

I don't see how this change fix anything: interp still points to freed bytes.

You should read interp->next before PyMem_RawFree(), and so change how the loop is written.

cc @ericsnowcurrently

Copy link
Contributor

eamanu Feb 14, 2019

Choose a reason for hiding this comment

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

When PyMem_RawFree(tmp_interp) the tmp_interp point to interp, so you are freed interp too, right?

What about this?

tmp_interp = interp->next;
for (; tmp_interp !=NULL; interp = tmp_interp){
...
tmp_interp = interp->next;
PyMem_RawFree(interp);
}

Copy link
Member Author

matrixise Feb 14, 2019

Choose a reason for hiding this comment

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

sure? the last time I have coded in C, that was in 2007 :/ ok

Copy link
Member Author

matrixise Feb 14, 2019

Choose a reason for hiding this comment

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

or just

PyInterpreterState *tmp_interp = NULL;
for (; interp != NULL;) {
    ...
    tmp_interp = interp;
    interp = interp->next;
    PyMem_RawFree(tmp_interp);
}

@vstinner and @eamanu

Copy link
Member Author

matrixise Feb 14, 2019

Choose a reason for hiding this comment

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

@eamanu are you on Zulip or IRC?

Copy link
Contributor

eamanu Feb 14, 2019

Choose a reason for hiding this comment

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

@matrixise I am connecting to zulip

Copy link
Member

JulienPalard Feb 14, 2019

Choose a reason for hiding this comment

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

With a while (interp) should work the same, and the jungling of tmp/interp looks good to me.

Copy link
Member Author

matrixise Feb 14, 2019

Choose a reason for hiding this comment

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

@JulienPalard I have just updated my PR, thanks for the review.
Now, I am going to wait for the review of @vstinner, he is more expert than me with the C language.

JulienPalard previously approved these changes Feb 14, 2019
Copy link
Member

JulienPalard left a comment

LGTM

Copy link
Contributor

eamanu left a comment

lgtm

matrixise changed the title bpo-35993: Fix an incorrect use of released memory WIP: bpo-35993: Fix an incorrect use of released memory Feb 14, 2019
Python/pystate.c Outdated
for (; interp != NULL; interp = interp->next) {
fprintf(stdout, "1. interp: %p\n", interp);
fprintf(stdout, "2. interp->next: %p\n", interp->next);
fprintf(stdout, "2.1. _PyRuntime.interpreters.main: %p\n", _PyRuntime.interpreters.main);
Copy link
Member

vstinner Feb 14, 2019

Choose a reason for hiding this comment

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

Remove debug printf.

Copy link
Member

JulienPalard Feb 14, 2019

Choose a reason for hiding this comment

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

(Those have been pushed recently to diagnose the "take infinite time to build when this code is added" / "make CI timeout" issue)

Copy link
Member Author

matrixise Feb 14, 2019

Choose a reason for hiding this comment

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

@vstinner yep, just for the debug and because I wanted to show you

Python/pystate.c Outdated Show resolved Hide resolved
Python/pystate.c Outdated Show resolved Hide resolved
Copy link

bedevere-bot commented Feb 14, 2019

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

Copy link
Member

vstinner left a comment

I don't understand how the current code can code: it must crash if I understand correctly.

Is the function called? You may modify the code to add abort(), run the full Python test suite and check if a test does crash.

If there is no crash, would it be possible to add a test?

cc @ericsnowcurrently

Copy link

vstinner commented Feb 14, 2019

for (; tmp_interp !=NULL; interp = tmp_interp){
...
tmp_interp = interp->next;
PyMem_RawFree(interp);
}

I prefer this version, especially if you rename tmp_interp to next_interp.

Copy link

JulienPalard commented Feb 14, 2019

Current version does not compile, runs indefinitely, making CI timeout.

Copy link
Author

matrixise commented Feb 14, 2019

@vstinner it's my fault if my PR is broken after the approval of @JulienPalard. But I am working on it and try to fix it.

Copy link
Author

matrixise commented Feb 14, 2019

@vstinner @ericsnowcurrently the current code is used when you compile Python, but there is no crash (un/fortunately)

Copy link
Member

JulienPalard left a comment

LGTM

Copy link
Author

matrixise commented Feb 14, 2019

@vstinner the code works and the tests pass. no lock on travis.

matrixise changed the title WIP: bpo-35993: Fix an incorrect use of released memory bpo-35993: Fix an incorrect use of released memory Feb 14, 2019
Copy link

vstinner commented Feb 14, 2019

@vstinner @ericsnowcurrently the current code is used when you compile Python

Would you mind to elaborate? I would like to make sure that the function is properly tested.

but there is no crash (un/fortunately)

Strange. So maybe the current code is just fine? Or we miss a test.

Copy link
Author

matrixise commented Feb 14, 2019

@vstinner example when you compile python

gcc -pthread -shared build/temp.linux-x86_64-3.8-pydebug/home/stephane/src/github.com/python/cpython/Modules/_contextvarsmodule.o -L/home/stephane/src/github.com/python/cpython-add_smtpshandler/lib -L/usr/local/lib -o build/lib.linux-x86_64-3.8-pydebug/_contextvars.cpython-38dm-x86_64-linux-gnu.so
1 _PyInterpreterState_DeleteExceptMain
2 _PyInterpreterState_DeleteExceptMain
#### _PyInterpreterState_DeleteExceptMain
building 'cmath' extension
gcc -pthread -fPIC -Wno-unused-result -Wsign-compare -g -Og -Wall -std=c99 -Wextra -Wno-unused-result -Wno-unused-parameter -Wno-missing-field-initializers -Werror=implicit-function-declaration -I./Include/internal -I./Include -I/home/stephane/src/github.com/python/cpython-add_smtpshandler/include -I. -I/usr/local/include -I/home/stephane/src/github.com/python/cpython/Include -I/home/stephane/src/github.com/python/cpython -c /home/stephane/src/github.com/python/cpython/Modules/cmathmodule.c -o build/temp.linux-x86_64-3.8-pydebug/home/stephane/src/github.com/python/cpython/Modules/cmathmodule.o
1 _PyInterpreterState_DeleteExceptMain
2 _PyInterpreterState_DeleteExceptMain
#### _PyInterpreterState_DeleteExceptMain

Copy link

vstinner commented Feb 14, 2019

Ok, but I guess that the code path which trigger the bug is not taken, since according to the bug tracker, it must crash. I guess that no test call this function with more than 1 interpreter. That's why I added @ericsnowcurrently in copy of this change :-)

Copy link

eamanu commented Feb 14, 2019

I am not sure when _PyInterpreterState_DeleteExceptMain() is called. This way we could test it. @vstinner @matrixise

Python/pystate.c Outdated Show resolved Hide resolved
Copy link
Author

matrixise commented Feb 15, 2019

@eamanu as you can see my paste in the previous comment, the function is called when we try to compile Python, certainly in the Makefile.

Copy link

methane commented Feb 15, 2019

I don't understand how the current code can code: it must crash if I understand correctly.

@vstinner this for loop iterate over (sub)interpreters.
When there is only main interpreter, PyMem_RawFree(interp); is never called.

cpython/Python/pystate.c

Lines 285 to 289 in 3e028b2

if (interp == _PyRuntime.interpreters.main) {
_PyRuntime.interpreters.main->next = NULL;
_PyRuntime.interpreters.head = interp;
continue;
}

Copy link
Author

matrixise commented Feb 18, 2019

@ericsnowcurrently Any advice for a test for this part?
Thank you,

@@ -0,0 +1 @@
Fix an incorrect use of released memory. Contributed by Stéphane Wirtel
Copy link
Member

vstinner Feb 18, 2019

Choose a reason for hiding this comment

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

Only from this NEWS entry, it's hard to know which code is impacted. I found PyOS_AfterFork_Child() which calls _PyInterpreterState_DeleteExceptMain(). I understand that the bug triggers if an application using multiple interpreters forks... it sounds like a very unusual use case. I propose:

"Fix a crash on fork when using subinterpreters. Contributed by Stéphane Wirtel."

Copy link
Author

matrixise commented Feb 20, 2019

@vstinner I have just updated the blurb entry, sorry I didn't see your notification

vstinner merged commit b5409da into python:master Feb 20, 2019
5 checks passed
Copy link

miss-islington commented Feb 20, 2019

Thanks @matrixise for the PR, and @vstinner for merging it 🌮🎉.. I'm working now to backport this PR to: 3.7.
🐍🍒🤖

Copy link

miss-islington commented Feb 20, 2019

Sorry, @matrixise and @vstinner, I could not cleanly backport this to 3.7 due to a conflict.
Please backport using cherry_picker on command line.
cherry_picker b5409dacc4885146a27d06482b346e55fa12d2ec 3.7

Copy link

vstinner commented Feb 20, 2019

Ah, it's a new function in Python 3.8. I didn't know. No need to backport in that case.

Copy link
Author

matrixise commented Feb 20, 2019

@vstinner thank you for the merge ;-) a good news for today ;-)

ma8ma pushed a commit to ma8ma/cpython that referenced this issue Apr 7, 2019
 Fix a crash on fork when using subinterpreters.
arnolddumas pushed a commit to arnolddumas/cpython that referenced this issue May 3, 2019
 Fix a crash on fork when using subinterpreters.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants