X-Git-Url: http://git.ozlabs.org/?a=blobdiff_plain;f=ccan%2Ftalloc%2Ftalloc.c;h=fdf8eebed297db56d26abdca812b515702ffdf02;hb=2d4243996a4ace6d4eac1da460dd5bbcb31304ce;hp=1424748eef7fa9a5b49caabd9fb095914b51cd50;hpb=f933b8c3246e3fbfe362cb1db73a4ef774725709;p=ccan diff --git a/ccan/talloc/talloc.c b/ccan/talloc/talloc.c index 1424748e..fdf8eebe 100644 --- a/ccan/talloc/talloc.c +++ b/ccan/talloc/talloc.c @@ -43,7 +43,7 @@ #define ALWAYS_REALLOC 0 -#define MAX_TALLOC_SIZE 0x10000000 +#define MAX_TALLOC_SIZE 0x7FFFFFFF #define TALLOC_MAGIC 0xe814ec70 #define TALLOC_FLAG_FREE 0x01 #define TALLOC_FLAG_LOOP 0x02 @@ -469,7 +469,7 @@ static void *__talloc_steal(const void *new_ctx, const void *ptr) /* internal talloc_free call */ -static inline int _talloc_free(void *ptr) +static inline int _talloc_free(const void *ptr) { struct talloc_chunk *tc; void *oldparent = NULL; @@ -508,7 +508,7 @@ static inline int _talloc_free(void *ptr) return -1; } tc->destructor = (talloc_destructor_t)-1; - if (d(ptr) == -1) { + if (d(discard_const_p(void, ptr)) == -1) { tc->destructor = d; return -1; } @@ -664,7 +664,7 @@ int talloc_unlink(const void *context, void *ptr) /* add a name to an existing pointer - va_list version */ -static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); +static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_FMT(2,0); static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) { @@ -789,6 +789,39 @@ void *_talloc(const void *context, size_t size) return __talloc(context, size); } +static int talloc_destroy_pointer(void ***pptr) +{ + if ((uintptr_t)**pptr < getpagesize()) + TALLOC_ABORT("Double free or invalid talloc_set?"); + /* Invalidate pointer so it can't be used again. */ + **pptr = (void *)1; + return 0; +} + +void _talloc_set(void *ptr, const void *ctx, size_t size, const char *name) +{ + void ***child; + void *p; + + p = talloc_named_const(ctx, size, name); + if (unlikely(!p)) + goto set_ptr; + + child = talloc(p, void **); + if (unlikely(!child)) { + talloc_free(p); + p = NULL; + goto set_ptr; + } + *child = ptr; + talloc_set_name_const(child, "talloc_set destructor"); + talloc_set_destructor(child, talloc_destroy_pointer); + +set_ptr: + /* memcpy rather than cast avoids aliasing problems. */ + memcpy(ptr, &p, sizeof(p)); +} + /* externally callable talloc_set_name_const() */ @@ -819,12 +852,12 @@ void *talloc_named_const(const void *context, size_t size, const char *name) will not be freed if the ref_count is > 1 or the destructor (if any) returns non-zero */ -int talloc_free(void *ptr) +int talloc_free(const void *ptr) { int saved_errno = errno, ret; lock(ptr); - ret = _talloc_free(ptr); + ret = _talloc_free(discard_const_p(void, ptr)); unlock(); if (ret == 0) errno = saved_errno;