From: Antoine Pitrou Date: Fri, 7 Jan 2011 21:49:44 +0000 (+0000) Subject: Merged revisions 87834 via svnmerge from X-Git-Tag: v2.7.2rc1~394 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5a72e76b6938941547dd25f9198db7d17fa36960;p=python Merged revisions 87834 via svnmerge from svn+ssh://pythondev@svn.python.org/python/branches/py3k ........ r87834 | antoine.pitrou | 2011-01-07 22:43:59 +0100 (ven., 07 janv. 2011) | 5 lines Issue #8020: Avoid a crash where the small objects allocator would read non-Python managed memory while it is being modified by another thread. Patch by Matt Bandy. ........ --- diff --git a/Misc/ACKS b/Misc/ACKS index aca3873d7c..8f55c5dbd5 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -41,6 +41,7 @@ Stig Bakken Greg Ball Luigi Ballabio Jeff Balogh +Matt Bandy Michael J. Barber Chris Barker Nick Barnes diff --git a/Misc/NEWS b/Misc/NEWS index 924f1f02f9..e436278970 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -9,6 +9,10 @@ What's New in Python 2.7.2? Core and Builtins ----------------- +- Issue #8020: Avoid a crash where the small objects allocator would read + non-Python managed memory while it is being modified by another thread. + Patch by Matt Bandy. + - Issue #8278: On Windows and with a NTFS filesystem, os.stat() and os.utime() can now handle dates after 2038. @@ -25,6 +29,13 @@ Core and Builtins Library ------- +- Issue #10827: Changed the rules for 2-digit years. The time.asctime + function will now format any year when ``time.accept2dyear`` is + false and will accept years >= 1000 otherwise. The year range + accepted by ``time.mktime`` and ``time.strftime`` is still system + dependent, but ``time.mktime`` will now accept full range supported + by the OS. Conversion of 2-digit years to 4-digit is deprecated. + - Issue #7858: Raise an error properly when os.utime() fails under Windows on an existing file. diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index 2e00b3ef7f..483847cad2 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -682,11 +682,19 @@ that this test determines whether an arbitrary address is controlled by obmalloc in a small constant time, independent of the number of arenas obmalloc controls. Since this test is needed at every entry point, it's extremely desirable that it be this fast. + +Since Py_ADDRESS_IN_RANGE may be reading from memory which was not allocated +by Python, it is important that (POOL)->arenaindex is read only once, as +another thread may be concurrently modifying the value without holding the +GIL. To accomplish this, the arenaindex_temp variable is used to store +(POOL)->arenaindex for the duration of the Py_ADDRESS_IN_RANGE macro's +execution. The caller of the macro is responsible for declaring this +variable. */ #define Py_ADDRESS_IN_RANGE(P, POOL) \ - ((POOL)->arenaindex < maxarenas && \ - (uptr)(P) - arenas[(POOL)->arenaindex].address < (uptr)ARENA_SIZE && \ - arenas[(POOL)->arenaindex].address != 0) + ((arenaindex_temp = (POOL)->arenaindex) < maxarenas && \ + (uptr)(P) - arenas[arenaindex_temp].address < (uptr)ARENA_SIZE && \ + arenas[arenaindex_temp].address != 0) /* This is only useful when running memory debuggers such as @@ -945,6 +953,9 @@ PyObject_Free(void *p) block *lastfree; poolp next, prev; uint size; +#ifndef Py_USING_MEMORY_DEBUGGER + uint arenaindex_temp; +#endif if (p == NULL) /* free(NULL) has no effect */ return; @@ -1167,6 +1178,9 @@ PyObject_Realloc(void *p, size_t nbytes) void *bp; poolp pool; size_t size; +#ifndef Py_USING_MEMORY_DEBUGGER + uint arenaindex_temp; +#endif if (p == NULL) return PyObject_Malloc(nbytes); @@ -1865,8 +1879,10 @@ _PyObject_DebugMallocStats(void) int Py_ADDRESS_IN_RANGE(void *P, poolp pool) { - return pool->arenaindex < maxarenas && - (uptr)P - arenas[pool->arenaindex].address < (uptr)ARENA_SIZE && - arenas[pool->arenaindex].address != 0; + uint arenaindex_temp = pool->arenaindex; + + return arenaindex_temp < maxarenas && + (uptr)P - arenas[arenaindex_temp].address < (uptr)ARENA_SIZE && + arenas[arenaindex_temp].address != 0; } #endif