Commit 918b0f00 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Change PyMem_Malloc to be gc_malloc instead of malloc

I didn't realize that pymem.h defined it originally to be malloc(),
which was messing things up when we would start allocating GC objects
using malloc().

Now that that's redefined, I *think* that as long as everything uses the
API functions, we shouldn't need to override / hook malloc().
There are a number of uses of raw malloc() in the Modules directory;
I hope that they're mostly string-related.
parent 2a66d281
......@@ -51,6 +51,10 @@ extern "C" {
performed on failure (no exception is set, no warning is printed, etc).
*/
PyAPI_FUNC(void *) gc_compat_malloc(size_t);
PyAPI_FUNC(void *) gc_compat_realloc(void *, size_t);
PyAPI_FUNC(void) gc_compat_free(void *);
PyAPI_FUNC(void *) PyMem_Malloc(size_t);
PyAPI_FUNC(void *) PyMem_Realloc(void *, size_t);
PyAPI_FUNC(void) PyMem_Free(void *);
......@@ -74,10 +78,10 @@ PyAPI_FUNC(void) PyMem_Free(void *);
/* Returns NULL to indicate error if a negative size or size larger than
Py_ssize_t can represent is supplied. Helps prevents security holes. */
#define PyMem_MALLOC(n) ((size_t)(n) > (size_t)PY_SSIZE_T_MAX ? NULL \
: malloc((n) ? (n) : 1))
: gc_compat_malloc((n) ? (n) : 1))
#define PyMem_REALLOC(p, n) ((size_t)(n) > (size_t)PY_SSIZE_T_MAX ? NULL \
: realloc((p), (n) ? (n) : 1))
#define PyMem_FREE free
: gc_compat_realloc((p), (n) ? (n) : 1))
#define PyMem_FREE gc_compat_free
#endif /* PYMALLOC_DEBUG */
......
......@@ -310,7 +310,7 @@ enum class GCKind : uint8_t {
UNTRACKED = 3,
};
void* gc_alloc(size_t nbytes, GCKind kind);
extern "C" void* gc_alloc(size_t nbytes, GCKind kind);
}
class PythonGCObject {
......
......@@ -68,6 +68,10 @@ static bool isNonheapRoot(void* p) {
return p <= max_nonheap_root && nonheap_roots.count(p) != 0;
}
bool isValidGCObject(void* p) {
return isNonheapRoot(p) || (global_heap.getAllocationFromInteriorPointer(p)->user_data == p);
}
static std::unordered_set<GCRootHandle*>* getRootHandles() {
static std::unordered_set<GCRootHandle*> root_handles;
return &root_handles;
......
......@@ -83,6 +83,8 @@ public:
};
void runCollection();
bool isValidGCObject(void* p);
}
}
......
// Copyright (c) 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "gc/gc_alloc.h"
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <stdint.h>
#include <sys/mman.h>
#include "core/common.h"
#include "core/util.h"
//#undef VERBOSITY
//#define VERBOSITY(x) 2
namespace pyston {
namespace gc {
extern "C" void* gc_compat_malloc(size_t sz) {
return gc_alloc(sz, GCKind::CONSERVATIVE);
}
extern "C" void* gc_compat_realloc(void* ptr, size_t sz) {
if (ptr == NULL)
return gc_alloc(sz, GCKind::CONSERVATIVE);
return gc_realloc(ptr, sz);
}
extern "C" void gc_compat_free(void* ptr) {
gc_free(ptr);
}
// We may need to hook malloc as well:
/*
extern "C" void* malloc(size_t sz) {
abort();
}
extern "C" void free(void* p) {
abort();
}
*/
} // namespace gc
} // namespace pyston
......@@ -27,8 +27,8 @@
namespace pyston {
namespace gc {
inline void* gc_alloc(size_t bytes, GCKind kind_id) __attribute__((visibility("default")));
inline void* gc_alloc(size_t bytes, GCKind kind_id) {
extern "C" inline void* gc_alloc(size_t bytes, GCKind kind_id) __attribute__((visibility("default")));
extern "C" inline void* gc_alloc(size_t bytes, GCKind kind_id) {
bytes += sizeof(GCAllocation);
#ifndef NVALGRIND
......@@ -68,8 +68,7 @@ inline void* gc_alloc(size_t bytes, GCKind kind_id) {
#ifndef NDEBUG
// I think I have a suspicion: the gc will see the constant and treat it as a
// root. So instead, shift to hide the pointer
// if ((((intptr_t)r) >> 4) == (0x127001424L)) {
// if ((((intptr_t)r) >> 4) == (0x127000718L)) {
// if ((((intptr_t)r) >> 4) == (0x127014f9f)) {
// raise(SIGTRAP);
//}
......@@ -81,8 +80,11 @@ inline void* gc_alloc(size_t bytes, GCKind kind_id) {
return r;
}
inline void* gc_realloc(void* ptr, size_t bytes) __attribute__((visibility("default")));
inline void* gc_realloc(void* ptr, size_t bytes) {
extern "C" inline void* gc_realloc(void* ptr, size_t bytes) __attribute__((visibility("default")));
extern "C" inline void* gc_realloc(void* ptr, size_t bytes) {
// Normal realloc() supports receiving a NULL pointer, but we need to know what the GCKind is:
assert(ptr);
bytes += sizeof(GCAllocation);
#ifndef NVALGRIND
......@@ -103,8 +105,9 @@ inline void* gc_realloc(void* ptr, size_t bytes) {
#endif
}
inline void gc_free(void* ptr) __attribute__((visibility("default")));
inline void gc_free(void* ptr) {
extern "C" inline void gc_free(void* ptr) __attribute__((visibility("default")));
extern "C" inline void gc_free(void* ptr) {
assert(ptr);
#ifndef NVALGRIND
if (ENABLE_REDZONES) {
void* base = (char*)ptr - REDZONE_SIZE;
......
......@@ -553,6 +553,7 @@ static const std::string _call_str("__call__"), _new_str("__new__"), _init_str("
void Box::setattr(const std::string& attr, Box* val, SetattrRewriteArgs* rewrite_args) {
assert(cls->instancesHaveAttrs());
assert(gc::isValidGCObject(val));
// Have to guard on the memory layout of this object.
// Right now, guard on the specific Python-class, which in turn
......@@ -1340,6 +1341,8 @@ extern "C" Box* getattr(Box* obj, const char* attr) {
}
static void setattr_internal(Box* obj, const std::string& attr, Box* val, SetattrRewriteArgs* rewrite_args) {
assert(gc::isValidGCObject(val));
// Lookup a descriptor
Box* descr = NULL;
RewriterVarUsage r_descr(RewriterVarUsage::empty());
......
# skip-if: True
# This test works but 1) is very slow [the importing is, not the regex itself], and 2) throws warnings
# This test also seems to leak a lot of memory.
import sre_compile
r = sre_compile.compile("a(b+)c", 0)
print r.match("")
print r.match("ac")
print r.match("abc").groups()
print r.match("abbc").groups()
for i in xrange(100000):
r.match("abbc").groups()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment