#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
/*
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;
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;
}
/*
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)
{
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()
*/