◐ Shell
reader mode source ↗
Skip to content

bpo-31626: Mark ends of the reallocated block in debug build.#4210

Merged
serhiy-storchaka merged 5 commits into
python:masterfrom
serhiy-storchaka:debug-realloc
Nov 7, 2017
Merged

bpo-31626: Mark ends of the reallocated block in debug build.#4210
serhiy-storchaka merged 5 commits into
python:masterfrom
serhiy-storchaka:debug-realloc

Conversation

@serhiy-storchaka

@serhiy-storchaka serhiy-storchaka commented Nov 1, 2017

Copy link
Copy Markdown
Member

Few bytes at the begin and at the end of the reallocated blocks, as well
as the header and the trailer, now are erased before calling realloc()
in debug build. This will help to detect using or double freeing the
reallocated block.

https://bugs.python.org/issue31626

Few bytes at the begin and at the end of the reallocated blocks, as well
as the header and the trailer, now are erased before calling realloc()
in debug build.  This will help to detect using or double freeing the
reallocated block.

@vstinner vstinner left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hide comment

Sorry, it's my fault, I misunderstood your code :-(

@vstinner vstinner left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hide comment

LGTM.

Congrats for implementing the feature with your very long list of constraints (no additional heap allocation, "correct" code, low stack memory usage, etc.). Your code is very smart, and I missed some parts on my first rounds of review.

Do you want to backport this change to other Python branches?

I don't think that it's needed since the current code (modify freed memory after realloc) "just works". It does crash on OpenBSD, but I'm not interested to support OpenBSD in Python 2.7 and 3.6, I prefer to focus on supporting it in the master branch.

@serhiy-storchaka

Copy link
Copy Markdown
Member Author

There was no crash on 2.7, and the fix for crash was backported to 3.6. This PR adds a new feature (the previous implementation didn't work, it was a dead code except OpenBSD where it caused a crash) that can help to catch memory bugs. I don't want to backport it.

@vstinner

vstinner commented Nov 6, 2017

Copy link
Copy Markdown
Member

(...) the fix for crash was backported to 3.6. This PR adds a new feature (the previous implementation didn't work, (...)

Oh, I didn't see that you already removed the memset() from 3.6.

In that case, I would suggest to backport this PR to Python 3.6 as well, to not loose the detection of "use after free" by debug hooks.

@serhiy-storchaka

serhiy-storchaka commented Nov 6, 2017

Copy link
Copy Markdown
Member Author

Left this on to @ned-deily. But note that this detection doesn't work since 3.4, and this change is much more complex than #4145.

@ned-deily

Copy link
Copy Markdown
Member

My reaction is that the risk due to complexity of the changes outweigh the benefits so I would agree with @serhiy-storchaka that we should not backport this.

@vstinner

vstinner commented Nov 7, 2017

Copy link
Copy Markdown
Member

My reaction is that the risk due to complexity of the changes outweigh the benefits so I would agree with @serhiy-storchaka that we should not backport this.

Ok, fine.

@vstinner

vstinner commented Nov 7, 2017

Copy link
Copy Markdown
Member

@serhiy-storchaka: For Python 3.6, what do you think of using Python 2.7 simple code?

...
    if (nbytes < original_nbytes) {
        /* shrinking:  mark old extra memory dead */
        memset(q + nbytes, DEADBYTE, original_nbytes - nbytes + 2*SST);
    }

    /* Resize and add decorations. We may get a new pointer here, in which
     * case we didn't get the chance to mark the old memory with DEADBYTE,
     * but we live with that.
     */
    q = (uchar *)PyObject_Realloc(q - 2*SST, total);
...

The code expect that realloc() never fails when shrinking. While Xavier De Gaye and me made realloc() failing anyway using tools to inject memory allocation failures, it seems like in the wild with system realloc(), realloc() never fails in that case.

If you agree, I can prepare a PR if you want. Or you can do, as you want :-)

For the master branch, I really prefer this PR since it's the "most correct" code: it supports hardcore testing as Xavier and me did ;-)

@serhiy-storchaka

Copy link
Copy Markdown
Member Author

This is what the initial version of #3844 did. But I agree with your arguments, adding this in 3.6 is risky. The third-party code in 3.6 can expect that realloc() don't change the content on failure.

@serhiy-storchaka serhiy-storchaka merged commit 3cc4c53 into python:master Nov 7, 2017
@serhiy-storchaka serhiy-storchaka deleted the debug-realloc branch November 7, 2017 10:46
embray pushed a commit to embray/cpython that referenced this pull request Nov 9, 2017
…#4210)

Few bytes at the begin and at the end of the reallocated blocks, as well
as the header and the trailer, now are erased before calling realloc()
in debug build.  This will help to detect using or double freeing the
reallocated block.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip news type-feature A feature request or enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants