| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
Signed-off-by: yihong0618 <zouzou0208@gmail.com>
There was a problem hiding this comment.
I don't like adding a new flushing variable here. To me it doesn't solves the core issue: Code assumes self->buffer is non-NULL because of checks which become invalid by the time it's actually dereferenced/used (TOCTOU general bug class). I think TextIOWrapper already has the information we need to be looking at / checking for (CHECK_ATTACHED macro / self->detached, self->buffer == NULL, and self->ok, ...). Those seem to be tracking very close to the same thing and should be usable to solve this group of issues.
I think it would be better here to use CHECK_ATTACHED just before self->buffer is used / passed to a call / returned; making sure there aren't any other calls to interpreter methods betwen the CHECK_ATTACHED + self->buffer usage / dereference.
I suspect BufferedIO will need a similar set of fixes: It also has a concept of an underlying stream that can be "detached" and which user code may detach during various operations.
Some comments on specifics inline, the test_textio ones I think are important in further changes, implementation details less so if not adding/using the flushing member.
Sorry, something went wrong.
| # instead of crashing. | ||
| wrapper = None | ||
|
|
||
| class BadRaw(self.RawIOBase): |
There was a problem hiding this comment.
There's a number of mock helpers defined in test_io/utils.py to make it so can reduce this to just the methods that matter. I think self.MockRawIO will work here
Sorry, something went wrong.
There was a problem hiding this comment.
thanks
Sorry, something went wrong.
| with self.subTest(name): | ||
| wrapper = self.TextIOWrapper(EvilBuffer(BadRaw()), encoding='utf-8') | ||
| self.assertRaisesRegex(RuntimeError, "reentrant", method) | ||
| wrapper = None |
There was a problem hiding this comment.
can we make the gc / closing here more explicit? del wrapper?
Sorry, something went wrong.
There was a problem hiding this comment.
thanks
Sorry, something went wrong.
| static inline int | ||
| _textiowrapper_flush(textio *self) | ||
| { | ||
| self->flushing = 1; |
There was a problem hiding this comment.
Why can't this be in _io_TextIOWrapper_flush_impl?
Sorry, something went wrong.
There was a problem hiding this comment.
it can, the design is cover it in _PyFile_Flush
Sorry, something went wrong.
There was a problem hiding this comment.
dropped
Sorry, something went wrong.
| PyObject *ret; | ||
| self->flushing = 1; | ||
| do { | ||
| ret = PyObject_CallMethodOneArg(self->buffer, &_Py_ID(write), b); |
There was a problem hiding this comment.
every loop iteration / write call could execute arbitrary interpreter code that could invalidate self->buffer so likely need to check on each loop iteration.
Sorry, something went wrong.
There was a problem hiding this comment.
will check, but I think maybe not need
Sorry, something went wrong.
There was a problem hiding this comment.
dropped
Sorry, something went wrong.
I think you are right but CHECK_ATTACHED in the middle of code is not a good name and easy to forget add it. |
Sorry, something went wrong.
|
And I can change it to my first solution or waiting for other discuss here? |
Sorry, something went wrong.
…akErJ.rst Co-authored-by: Cody Maloney <cmaloney@users.noreply.github.com>
|
I agree CHECK_ATTACHED is easy to forget and I'd argue this bug is the result of some cases missing it.. It is a relatively small change though and matches the rest of the textio.c code style / convention. I have been working towards changing textio.c more generally, but that's too big for a likely back-ported bugfix. Can you explain what your first solution is? I'm not understanding what you're referring to. |
Sorry, something went wrong.
|
Sorry, something went wrong.
There was a problem hiding this comment.
This will break the case when flush() was intentionally overridden.
I am not also sure that it fixes the core issue, it just makes a particular reproducer no longer working.
Sorry, something went wrong.
will dig it, thank you |
Sorry, something went wrong.
after some check and work I do not think CHECK_ATTACHED before every is a good design will dig more |
Sorry, something went wrong.
Signed-off-by: yihong0618 <zouzou0208@gmail.com>
I made some change but not sure its better idea, can you help to check? Thank you very much. if you have better way to fix all of them feel free to close it~ thanks again |
Sorry, something went wrong.
|
I'm starting to think a small refactor of TextIOWrapper to add and use a helper that always checks self->ok + self->attached would be better here; wrote up more thoughts in #143008 (comment) |
Sorry, something went wrong.
will try to understand and learn it thank you |
Sorry, something went wrong.
TextIOWrapper keeps its underlying stream in a member called `self->buffer`. That stream can be detached by user code, such as custom `.flush` implementations resulting in `self->buffer` being set to NULL. The implementation often checked at the start of functions if `self->buffer` is in a good state, but did not always recheck after other Python code was called which could modify `self->buffer`. The cases which need to be re-checked are hard to spot so rather than rely on reviewer effort create better safety by making all self->buffer access go through helper functions. Thank you yihong0618 for the test, NEWS and initial implementation in pythongh-143041. Co-authored-by: yihong0618 <zouzou0208@gmail.com>
|
This PR is stale because it has been open for 30 days with no activity. |
Sorry, something went wrong.
…stream access (#145957) TextIOWrapper keeps its underlying stream in a member called `self->buffer`. That stream can be detached by user code, such as custom `.flush` implementations resulting in `self->buffer` being set to NULL. The implementation often checked at the start of functions if `self->buffer` is in a good state, but did not always recheck after other Python code was called which could modify `self->buffer`. The cases which need to be re-checked are hard to spot so rather than rely on reviewer effort create better safety by making all self->buffer access go through helper functions. Thank you yihong0618 for the test, NEWS and initial implementation in gh-143041. Co-authored-by: yihong0618 <zouzou0208@gmail.com> Co-authored-by: Victor Stinner <vstinner@python.org>
|
#145957 was merged instead. Thanks for your contribution anyway! The merged change is based on your work and you're credited in the change ;-) |
Sorry, something went wrong.
…lying stream access (python#145957) TextIOWrapper keeps its underlying stream in a member called `self->buffer`. That stream can be detached by user code, such as custom `.flush` implementations resulting in `self->buffer` being set to NULL. The implementation often checked at the start of functions if `self->buffer` is in a good state, but did not always recheck after other Python code was called which could modify `self->buffer`. The cases which need to be re-checked are hard to spot so rather than rely on reviewer effort create better safety by making all self->buffer access go through helper functions. Thank you yihong0618 for the test, NEWS and initial implementation in pythongh-143041. Co-authored-by: yihong0618 <zouzou0208@gmail.com> Co-authored-by: Victor Stinner <vstinner@python.org>
…rant detach (#159591) * gh-143008: Fix Null pointer dereferences in TextIOWrapper underlying stream access (#145957) TextIOWrapper keeps its underlying stream in a member called `self->buffer`. That stream can be detached by user code, such as custom `.flush` implementations resulting in `self->buffer` being set to NULL. The implementation often checked at the start of functions if `self->buffer` is in a good state, but did not always recheck after other Python code was called which could modify `self->buffer`. The cases which need to be re-checked are hard to spot so rather than rely on reviewer effort create better safety by making all self->buffer access go through helper functions. Thank you yihong0618 for the test, NEWS and initial implementation in gh-143041. Co-authored-by: yihong0618 <zouzou0208@gmail.com> Co-authored-by: Victor Stinner <vstinner@python.org> (cherry picked from commit db4b194) * gh-154523: Fix data-race in `TextIOWrapper.detach()` (#154565) (cherry picked from commit 8440a6a) * gh-157364: Fix use-after-free in io.TextIOWrapper during reentrant detach (#157370) Co-authored-by: Victor Stinner <vstinner@python.org> (cherry picked from commit e19dc47) --------- Co-authored-by: Cody Maloney <cmaloney@users.noreply.github.com> Co-authored-by: yihong0618 <zouzou0208@gmail.com> Co-authored-by: Brij Kapadia <97006829+brijkapadia@users.noreply.github.com> Co-authored-by: Shamil <ashm.tech@proton.me>
…rant detach (#159600) [3.15] gh-157364: Fix use-after-free in io.TextIOWrapper during reentrant detach (#159591) * gh-143008: Fix Null pointer dereferences in TextIOWrapper underlying stream access (#145957) TextIOWrapper keeps its underlying stream in a member called `self->buffer`. That stream can be detached by user code, such as custom `.flush` implementations resulting in `self->buffer` being set to NULL. The implementation often checked at the start of functions if `self->buffer` is in a good state, but did not always recheck after other Python code was called which could modify `self->buffer`. The cases which need to be re-checked are hard to spot so rather than rely on reviewer effort create better safety by making all self->buffer access go through helper functions. Thank you yihong0618 for the test, NEWS and initial implementation in gh-143041. (cherry picked from commit db4b194) * gh-154523: Fix data-race in `TextIOWrapper.detach()` (#154565) (cherry picked from commit 8440a6a) * gh-157364: Fix use-after-free in io.TextIOWrapper during reentrant detach (#157370) (cherry picked from commit e19dc47) --------- (cherry picked from commit ea1312b) Co-authored-by: Cody Maloney <cmaloney@users.noreply.github.com> Co-authored-by: yihong0618 <zouzou0208@gmail.com> Co-authored-by: Brij Kapadia <97006829+brijkapadia@users.noreply.github.com> Co-authored-by: Shamil <ashm.tech@proton.me>
| Back | FazBrowse Home | New Git URL |
This patch fix all re-entrant flush problem
by adding an attr flushing
and. refactor the file check to _textiowrapper_flush
all crash problem in 143008 can be fix cc @jackfromeast can you help to check?
thank you very much!