Ignore:
Timestamp:
Nov 24, 2016, 1:14:11 PM (9 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to version 4.4.3

File:
1 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/lib/talloc/talloc.c

    r746 r988  
    1 /* 
     1/*
    22   Samba Unix SMB/CIFS implementation.
    33
     
    88   Copyright (C) Andrew Tridgell 2004
    99   Copyright (C) Stefan Metzmacher 2006
    10    
     10
    1111     ** NOTE! The following LGPL license applies to the talloc
    1212     ** library. This does NOT imply that all of Samba is released
    1313     ** under the LGPL
    14    
     14
    1515   This library is free software; you can redistribute it and/or
    1616   modify it under the terms of the GNU Lesser General Public
     
    3333#include "replace.h"
    3434#include "talloc.h"
     35
     36#ifdef HAVE_SYS_AUXV_H
     37#include <sys/auxv.h>
     38#endif
    3539
    3640#ifdef TALLOC_BUILD_VERSION_MAJOR
     
    6165
    6266#define MAX_TALLOC_SIZE 0x10000000
    63 #define TALLOC_MAGIC_BASE 0xe814ec70
    64 #define TALLOC_MAGIC ( \
    65         TALLOC_MAGIC_BASE + \
    66         (TALLOC_VERSION_MAJOR << 12) + \
    67         (TALLOC_VERSION_MINOR << 4) \
    68 )
    6967
    7068#define TALLOC_FLAG_FREE 0x01
     
    7270#define TALLOC_FLAG_POOL 0x04           /* This is a talloc pool */
    7371#define TALLOC_FLAG_POOLMEM 0x08        /* This is allocated in a pool */
     72
     73/*
     74 * Bits above this are random, used to make it harder to fake talloc
     75 * headers during an attack.  Try not to change this without good reason.
     76 */
     77#define TALLOC_FLAG_MASK 0x0F
     78
    7479#define TALLOC_MAGIC_REFERENCE ((const char *)1)
    7580
    76 /* by default we abort when given a bad pointer (such as when talloc_free() is called
     81#define TALLOC_MAGIC_BASE 0xe814ec70
     82static unsigned int talloc_magic = (
     83        TALLOC_MAGIC_BASE +
     84        (TALLOC_VERSION_MAJOR << 12) +
     85        (TALLOC_VERSION_MINOR << 4));
     86
     87/* by default we abort when given a bad pointer (such as when talloc_free() is called
    7788   on a pointer that came from malloc() */
    7889#ifndef TALLOC_ABORT
     
    228239};
    229240
     241struct talloc_memlimit {
     242        struct talloc_chunk *parent;
     243        struct talloc_memlimit *upper;
     244        size_t max_size;
     245        size_t cur_size;
     246};
     247
     248static inline bool talloc_memlimit_check(struct talloc_memlimit *limit, size_t size);
     249static inline void talloc_memlimit_grow(struct talloc_memlimit *limit,
     250                                size_t size);
     251static inline void talloc_memlimit_shrink(struct talloc_memlimit *limit,
     252                                size_t size);
     253static inline void talloc_memlimit_update_on_free(struct talloc_chunk *tc);
     254
     255static inline void _talloc_set_name_const(const void *ptr, const char *name);
     256
    230257typedef int (*talloc_destructor_t)(void *);
    231258
     259struct talloc_pool_hdr;
     260
    232261struct talloc_chunk {
     262        unsigned flags;
    233263        struct talloc_chunk *next, *prev;
    234264        struct talloc_chunk *parent, *child;
     
    237267        const char *name;
    238268        size_t size;
    239         unsigned flags;
    240269
    241270        /*
    242          * "pool" has dual use:
    243          *
    244          * For the talloc pool itself (i.e. TALLOC_FLAG_POOL is set), "pool"
    245          * marks the end of the currently allocated area.
    246          *
    247          * For members of the pool (i.e. TALLOC_FLAG_POOLMEM is set), "pool"
     271         * limit semantics:
     272         * if 'limit' is set it means all *new* children of the context will
     273         * be limited to a total aggregate size ox max_size for memory
     274         * allocations.
     275         * cur_size is used to keep track of the current use
     276         */
     277        struct talloc_memlimit *limit;
     278
     279        /*
     280         * For members of a pool (i.e. TALLOC_FLAG_POOLMEM is set), "pool"
    248281         * is a pointer to the struct talloc_chunk of the pool that it was
    249282         * allocated from. This way children can quickly find the pool to chew
    250283         * from.
    251284         */
    252         void *pool;
     285        struct talloc_pool_hdr *pool;
    253286};
    254287
     
    268301}
    269302
     303_PUBLIC_ int talloc_test_get_magic(void)
     304{
     305        return talloc_magic;
     306}
     307
    270308static void (*talloc_log_fn)(const char *message);
    271309
     
    274312        talloc_log_fn = log_fn;
    275313}
     314
     315#ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
     316void talloc_lib_init(void) __attribute__((constructor));
     317void talloc_lib_init(void)
     318{
     319        uint32_t random_value;
     320#if defined(HAVE_GETAUXVAL) && defined(AT_RANDOM)
     321        uint8_t *p;
     322        /*
     323         * Use the kernel-provided random values used for
     324         * ASLR.  This won't change per-exec, which is ideal for us
     325         */
     326        p = (uint8_t *) getauxval(AT_RANDOM);
     327        if (p) {
     328                /*
     329                 * We get 16 bytes from getauxval.  By calling rand(),
     330                 * a totally insecure PRNG, but one that will
     331                 * deterministically have a different value when called
     332                 * twice, we ensure that if two talloc-like libraries
     333                 * are somehow loaded in the same address space, that
     334                 * because we choose different bytes, we will keep the
     335                 * protection against collision of multiple talloc
     336                 * libs.
     337                 *
     338                 * This protection is important because the effects of
     339                 * passing a talloc pointer from one to the other may
     340                 * be very hard to determine.
     341                 */
     342                int offset = rand() % (16 - sizeof(random_value));
     343                memcpy(&random_value, p + offset, sizeof(random_value));
     344        } else
     345#endif
     346        {
     347                /*
     348                 * Otherwise, hope the location we are loaded in
     349                 * memory is randomised by someone else
     350                 */
     351                random_value = ((uintptr_t)talloc_lib_init & 0xFFFFFFFF);
     352        }
     353        talloc_magic = random_value & ~TALLOC_FLAG_MASK;
     354}
     355#else
     356#warning "No __attribute__((constructor)) support found on this platform, additional talloc security measures not available"
     357#endif
    276358
    277359static void talloc_log(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2);
     
    323405static void talloc_abort_magic(unsigned magic)
    324406{
    325         unsigned striped = magic - TALLOC_MAGIC_BASE;
    326         unsigned major = (striped & 0xFFFFF000) >> 12;
    327         unsigned minor = (striped & 0x00000FF0) >> 4;
    328         talloc_log("Bad talloc magic[0x%08X/%u/%u] expected[0x%08X/%u/%u]\n",
    329                    magic, major, minor,
    330                    TALLOC_MAGIC, TALLOC_VERSION_MAJOR, TALLOC_VERSION_MINOR);
    331407        talloc_abort("Bad talloc magic value - wrong talloc version used/mixed");
    332408}
     
    347423        const char *pp = (const char *)ptr;
    348424        struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
    349         if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~0xF)) != TALLOC_MAGIC)) {
    350                 if ((tc->flags & (~0xFFF)) == TALLOC_MAGIC_BASE) {
    351                         talloc_abort_magic(tc->flags & (~0xF));
     425        if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~TALLOC_FLAG_MASK)) != talloc_magic)) {
     426                if ((tc->flags & (~0xF)) == talloc_magic) {
     427                        talloc_abort_magic(tc->flags & (~TALLOC_FLAG_MASK));
    352428                        return NULL;
    353429                }
     
    438514*/
    439515
    440 #define TALLOC_POOL_HDR_SIZE 16
    441 
    442 #define TC_POOL_SPACE_LEFT(_pool_tc) \
    443         PTR_DIFF(TC_HDR_SIZE + (_pool_tc)->size + (char *)(_pool_tc), \
    444                  (_pool_tc)->pool)
    445 
    446 #define TC_POOL_FIRST_CHUNK(_pool_tc) \
    447         ((void *)(TC_HDR_SIZE + TALLOC_POOL_HDR_SIZE + (char *)(_pool_tc)))
    448 
    449 #define TC_POOLMEM_CHUNK_SIZE(_tc) \
    450         TC_ALIGN16(TC_HDR_SIZE + (_tc)->size)
    451 
    452 #define TC_POOLMEM_NEXT_CHUNK(_tc) \
    453         ((void *)(TC_POOLMEM_CHUNK_SIZE(tc) + (char*)(_tc)))
     516struct talloc_pool_hdr {
     517        void *end;
     518        unsigned int object_count;
     519        size_t poolsize;
     520};
     521
     522#define TP_HDR_SIZE TC_ALIGN16(sizeof(struct talloc_pool_hdr))
     523
     524static inline struct talloc_pool_hdr *talloc_pool_from_chunk(struct talloc_chunk *c)
     525{
     526        return (struct talloc_pool_hdr *)((char *)c - TP_HDR_SIZE);
     527}
     528
     529static inline struct talloc_chunk *talloc_chunk_from_pool(struct talloc_pool_hdr *h)
     530{
     531        return (struct talloc_chunk *)((char *)h + TP_HDR_SIZE);
     532}
     533
     534static inline void *tc_pool_end(struct talloc_pool_hdr *pool_hdr)
     535{
     536        struct talloc_chunk *tc = talloc_chunk_from_pool(pool_hdr);
     537        return (char *)tc + TC_HDR_SIZE + pool_hdr->poolsize;
     538}
     539
     540static inline size_t tc_pool_space_left(struct talloc_pool_hdr *pool_hdr)
     541{
     542        return (char *)tc_pool_end(pool_hdr) - (char *)pool_hdr->end;
     543}
     544
     545/* If tc is inside a pool, this gives the next neighbour. */
     546static inline void *tc_next_chunk(struct talloc_chunk *tc)
     547{
     548        return (char *)tc + TC_ALIGN16(TC_HDR_SIZE + tc->size);
     549}
     550
     551static inline void *tc_pool_first_chunk(struct talloc_pool_hdr *pool_hdr)
     552{
     553        struct talloc_chunk *tc = talloc_chunk_from_pool(pool_hdr);
     554        return tc_next_chunk(tc);
     555}
    454556
    455557/* Mark the whole remaining pool as not accessable */
    456 #define TC_INVALIDATE_FILL_POOL(_pool_tc) do { \
    457         if (unlikely(talloc_fill.enabled)) { \
    458                 size_t _flen = TC_POOL_SPACE_LEFT(_pool_tc); \
    459                 char *_fptr = (char *)(_pool_tc)->pool; \
    460                 memset(_fptr, talloc_fill.fill_value, _flen); \
    461         } \
    462 } while(0)
     558static inline void tc_invalidate_pool(struct talloc_pool_hdr *pool_hdr)
     559{
     560        size_t flen = tc_pool_space_left(pool_hdr);
     561
     562        if (unlikely(talloc_fill.enabled)) {
     563                memset(pool_hdr->end, talloc_fill.fill_value, flen);
     564        }
    463565
    464566#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
    465 /* Mark the whole remaining pool as not accessable */
    466 #define TC_INVALIDATE_VALGRIND_POOL(_pool_tc) do { \
    467         size_t _flen = TC_POOL_SPACE_LEFT(_pool_tc); \
    468         char *_fptr = (char *)(_pool_tc)->pool; \
    469         VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \
    470 } while(0)
    471 #else
    472 #define TC_INVALIDATE_VALGRIND_POOL(_pool_tc) do { } while (0)
    473 #endif
    474 
    475 #define TC_INVALIDATE_POOL(_pool_tc) do { \
    476         TC_INVALIDATE_FILL_POOL(_pool_tc); \
    477         TC_INVALIDATE_VALGRIND_POOL(_pool_tc); \
    478 } while (0)
    479 
    480 static unsigned int *talloc_pool_objectcount(struct talloc_chunk *tc)
    481 {
    482         return (unsigned int *)((char *)tc + TC_HDR_SIZE);
     567        VALGRIND_MAKE_MEM_NOACCESS(pool_hdr->end, flen);
     568#endif
    483569}
    484570
     
    487573*/
    488574
    489 static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent,
    490                                               size_t size)
    491 {
    492         struct talloc_chunk *pool_ctx = NULL;
     575static inline struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent,
     576                                                     size_t size, size_t prefix_len)
     577{
     578        struct talloc_pool_hdr *pool_hdr = NULL;
    493579        size_t space_left;
    494580        struct talloc_chunk *result;
     
    500586
    501587        if (parent->flags & TALLOC_FLAG_POOL) {
    502                 pool_ctx = parent;
     588                pool_hdr = talloc_pool_from_chunk(parent);
    503589        }
    504590        else if (parent->flags & TALLOC_FLAG_POOLMEM) {
    505                 pool_ctx = (struct talloc_chunk *)parent->pool;
    506         }
    507 
    508         if (pool_ctx == NULL) {
     591                pool_hdr = parent->pool;
     592        }
     593
     594        if (pool_hdr == NULL) {
    509595                return NULL;
    510596        }
    511597
    512         space_left = TC_POOL_SPACE_LEFT(pool_ctx);
     598        space_left = tc_pool_space_left(pool_hdr);
    513599
    514600        /*
    515601         * Align size to 16 bytes
    516602         */
    517         chunk_size = TC_ALIGN16(size);
     603        chunk_size = TC_ALIGN16(size + prefix_len);
    518604
    519605        if (space_left < chunk_size) {
     
    521607        }
    522608
    523         result = (struct talloc_chunk *)pool_ctx->pool;
     609        result = (struct talloc_chunk *)((char *)pool_hdr->end + prefix_len);
    524610
    525611#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
    526         VALGRIND_MAKE_MEM_UNDEFINED(result, size);
    527 #endif
    528 
    529         pool_ctx->pool = (void *)((char *)result + chunk_size);
    530 
    531         result->flags = TALLOC_MAGIC | TALLOC_FLAG_POOLMEM;
    532         result->pool = pool_ctx;
    533 
    534         *talloc_pool_objectcount(pool_ctx) += 1;
     612        VALGRIND_MAKE_MEM_UNDEFINED(pool_hdr->end, chunk_size);
     613#endif
     614
     615        pool_hdr->end = (void *)((char *)pool_hdr->end + chunk_size);
     616
     617        result->flags = talloc_magic | TALLOC_FLAG_POOLMEM;
     618        result->pool = pool_hdr;
     619
     620        pool_hdr->object_count++;
    535621
    536622        return result;
    537623}
    538624
    539 /* 
     625/*
    540626   Allocate a bit of memory as a child of an existing pointer
    541627*/
    542 static inline void *__talloc(const void *context, size_t size)
     628static inline void *__talloc_with_prefix(const void *context, size_t size,
     629                                        size_t prefix_len)
    543630{
    544631        struct talloc_chunk *tc = NULL;
     632        struct talloc_memlimit *limit = NULL;
     633        size_t total_len = TC_HDR_SIZE + size + prefix_len;
    545634
    546635        if (unlikely(context == NULL)) {
     
    552641        }
    553642
     643        if (unlikely(total_len < TC_HDR_SIZE)) {
     644                return NULL;
     645        }
     646
    554647        if (context != NULL) {
    555                 tc = talloc_alloc_pool(talloc_chunk_from_ptr(context),
    556                                        TC_HDR_SIZE+size);
     648                struct talloc_chunk *ptc = talloc_chunk_from_ptr(context);
     649
     650                if (ptc->limit != NULL) {
     651                        limit = ptc->limit;
     652                }
     653
     654                tc = talloc_alloc_pool(ptc, TC_HDR_SIZE+size, prefix_len);
    557655        }
    558656
    559657        if (tc == NULL) {
    560                 tc = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size);
    561                 if (unlikely(tc == NULL)) return NULL;
    562                 tc->flags = TALLOC_MAGIC;
     658                char *ptr;
     659
     660                /*
     661                 * Only do the memlimit check/update on actual allocation.
     662                 */
     663                if (!talloc_memlimit_check(limit, total_len)) {
     664                        errno = ENOMEM;
     665                        return NULL;
     666                }
     667
     668                ptr = malloc(total_len);
     669                if (unlikely(ptr == NULL)) {
     670                        return NULL;
     671                }
     672                tc = (struct talloc_chunk *)(ptr + prefix_len);
     673                tc->flags = talloc_magic;
    563674                tc->pool  = NULL;
    564         }
    565 
     675
     676                talloc_memlimit_grow(limit, total_len);
     677        }
     678
     679        tc->limit = limit;
    566680        tc->size = size;
    567681        tc->destructor = NULL;
     
    590704}
    591705
     706static inline void *__talloc(const void *context, size_t size)
     707{
     708        return __talloc_with_prefix(context, size, 0);
     709}
     710
    592711/*
    593712 * Create a talloc pool
    594713 */
    595714
    596 _PUBLIC_ void *talloc_pool(const void *context, size_t size)
    597 {
    598         void *result = __talloc(context, size + TALLOC_POOL_HDR_SIZE);
     715static inline void *_talloc_pool(const void *context, size_t size)
     716{
    599717        struct talloc_chunk *tc;
     718        struct talloc_pool_hdr *pool_hdr;
     719        void *result;
     720
     721        result = __talloc_with_prefix(context, size, TP_HDR_SIZE);
    600722
    601723        if (unlikely(result == NULL)) {
     
    604726
    605727        tc = talloc_chunk_from_ptr(result);
     728        pool_hdr = talloc_pool_from_chunk(tc);
    606729
    607730        tc->flags |= TALLOC_FLAG_POOL;
    608         tc->pool = TC_POOL_FIRST_CHUNK(tc);
    609 
    610         *talloc_pool_objectcount(tc) = 1;
    611 
    612         TC_INVALIDATE_POOL(tc);
     731        tc->size = 0;
     732
     733        pool_hdr->object_count = 1;
     734        pool_hdr->end = result;
     735        pool_hdr->poolsize = size;
     736
     737        tc_invalidate_pool(pool_hdr);
    613738
    614739        return result;
     740}
     741
     742_PUBLIC_ void *talloc_pool(const void *context, size_t size)
     743{
     744        return _talloc_pool(context, size);
     745}
     746
     747/*
     748 * Create a talloc pool correctly sized for a basic size plus
     749 * a number of subobjects whose total size is given. Essentially
     750 * a custom allocator for talloc to reduce fragmentation.
     751 */
     752
     753_PUBLIC_ void *_talloc_pooled_object(const void *ctx,
     754                                     size_t type_size,
     755                                     const char *type_name,
     756                                     unsigned num_subobjects,
     757                                     size_t total_subobjects_size)
     758{
     759        size_t poolsize, subobjects_slack, tmp;
     760        struct talloc_chunk *tc;
     761        struct talloc_pool_hdr *pool_hdr;
     762        void *ret;
     763
     764        poolsize = type_size + total_subobjects_size;
     765
     766        if ((poolsize < type_size) || (poolsize < total_subobjects_size)) {
     767                goto overflow;
     768        }
     769
     770        if (num_subobjects == UINT_MAX) {
     771                goto overflow;
     772        }
     773        num_subobjects += 1;       /* the object body itself */
     774
     775        /*
     776         * Alignment can increase the pool size by at most 15 bytes per object
     777         * plus alignment for the object itself
     778         */
     779        subobjects_slack = (TC_HDR_SIZE + TP_HDR_SIZE + 15) * num_subobjects;
     780        if (subobjects_slack < num_subobjects) {
     781                goto overflow;
     782        }
     783
     784        tmp = poolsize + subobjects_slack;
     785        if ((tmp < poolsize) || (tmp < subobjects_slack)) {
     786                goto overflow;
     787        }
     788        poolsize = tmp;
     789
     790        ret = _talloc_pool(ctx, poolsize);
     791        if (ret == NULL) {
     792                return NULL;
     793        }
     794
     795        tc = talloc_chunk_from_ptr(ret);
     796        tc->size = type_size;
     797
     798        pool_hdr = talloc_pool_from_chunk(tc);
     799
     800#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
     801        VALGRIND_MAKE_MEM_UNDEFINED(pool_hdr->end, type_size);
     802#endif
     803
     804        pool_hdr->end = ((char *)pool_hdr->end + TC_ALIGN16(type_size));
     805
     806        _talloc_set_name_const(ret, type_name);
     807        return ret;
     808
     809overflow:
     810        return NULL;
    615811}
    616812
     
    628824
    629825/*
    630   increase the reference count on a piece of memory. 
     826  increase the reference count on a piece of memory.
    631827*/
    632828_PUBLIC_ int talloc_increase_ref_count(const void *ptr)
     
    651847
    652848/*
    653    more efficient way to add a name to a pointer - the name must point to a 
     849   more efficient way to add a name to a pointer - the name must point to a
    654850   true string constant
    655851*/
     
    681877  the pointer remains valid until both the original caller and this given
    682878  context are freed.
    683  
    684   the major use for this is when two different structures need to reference the 
     879
     880  the major use for this is when two different structures need to reference the
    685881  same underlying data, and you want to be able to free the two instances separately,
    686882  and in either order
     
    713909                                        const char *location)
    714910{
    715         struct talloc_chunk *pool;
     911        struct talloc_pool_hdr *pool;
     912        struct talloc_chunk *pool_tc;
    716913        void *next_tc;
    717         unsigned int *pool_object_count;
    718 
    719         pool = (struct talloc_chunk *)tc->pool;
    720         next_tc = TC_POOLMEM_NEXT_CHUNK(tc);
     914
     915        pool = tc->pool;
     916        pool_tc = talloc_chunk_from_pool(pool);
     917        next_tc = tc_next_chunk(tc);
    721918
    722919        tc->flags |= TALLOC_FLAG_FREE;
     
    730927        TC_INVALIDATE_FULL_CHUNK(tc);
    731928
    732         pool_object_count = talloc_pool_objectcount(pool);
    733 
    734         if (unlikely(*pool_object_count == 0)) {
     929        if (unlikely(pool->object_count == 0)) {
    735930                talloc_abort("Pool object count zero!");
    736931                return;
    737932        }
    738933
    739         *pool_object_count -= 1;
    740 
    741         if (unlikely(*pool_object_count == 1 && !(pool->flags & TALLOC_FLAG_FREE))) {
     934        pool->object_count--;
     935
     936        if (unlikely(pool->object_count == 1
     937                     && !(pool_tc->flags & TALLOC_FLAG_FREE))) {
    742938                /*
    743939                 * if there is just one object left in the pool
     
    747943                 * again.
    748944                 */
    749                 pool->pool = TC_POOL_FIRST_CHUNK(pool);
    750                 TC_INVALIDATE_POOL(pool);
    751         } else if (unlikely(*pool_object_count == 0)) {
     945                pool->end = tc_pool_first_chunk(pool);
     946                tc_invalidate_pool(pool);
     947                return;
     948        }
     949
     950        if (unlikely(pool->object_count == 0)) {
    752951                /*
    753952                 * we mark the freed memory with where we called the free
     
    755954                 * the first free came from
    756955                 */
    757                 pool->name = location;
    758 
    759                 TC_INVALIDATE_FULL_CHUNK(pool);
    760                 free(pool);
    761         } else if (pool->pool == next_tc) {
     956                pool_tc->name = location;
     957
     958                if (pool_tc->flags & TALLOC_FLAG_POOLMEM) {
     959                        _talloc_free_poolmem(pool_tc, location);
     960                } else {
     961                        /*
     962                         * The talloc_memlimit_update_on_free()
     963                         * call takes into account the
     964                         * prefix TP_HDR_SIZE allocated before
     965                         * the pool talloc_chunk.
     966                         */
     967                        talloc_memlimit_update_on_free(pool_tc);
     968                        TC_INVALIDATE_FULL_CHUNK(pool_tc);
     969                        free(pool);
     970                }
     971                return;
     972        }
     973
     974        if (pool->end == next_tc) {
    762975                /*
    763976                 * if pool->pool still points to end of
     
    765978                 * we can reclaim the memory of 'tc'.
    766979                 */
    767                 pool->pool = tc;
    768         }
     980                pool->end = tc;
     981                return;
     982        }
     983
     984        /*
     985         * Do nothing. The memory is just "wasted", waiting for the pool
     986         * itself to be freed.
     987         */
    769988}
    770989
     
    773992                                                  const char *location);
    774993
    775 /* 
     994/*
    776995   internal talloc_free call
    777996*/
     
    779998{
    780999        struct talloc_chunk *tc;
     1000        void *ptr_to_free;
    7811001
    7821002        if (unlikely(ptr == NULL)) {
     
    8251045                tc->destructor = (talloc_destructor_t)-1;
    8261046                if (d(ptr) == -1) {
    827                         tc->destructor = d;
     1047                        /*
     1048                         * Only replace the destructor pointer if
     1049                         * calling the destructor didn't modify it.
     1050                         */
     1051                        if (tc->destructor == (talloc_destructor_t)-1) {
     1052                                tc->destructor = d;
     1053                        }
    8281054                        return -1;
    8291055                }
     
    8501076        /* we mark the freed memory with where we called the free
    8511077         * from. This means on a double free error we can report where
    852          * the first free came from 
    853          */     
     1078         * the first free came from
     1079         */
    8541080        tc->name = location;
    8551081
    8561082        if (tc->flags & TALLOC_FLAG_POOL) {
    857                 unsigned int *pool_object_count;
    858 
    859                 pool_object_count = talloc_pool_objectcount(tc);
    860 
    861                 if (unlikely(*pool_object_count == 0)) {
     1083                struct talloc_pool_hdr *pool;
     1084
     1085                pool = talloc_pool_from_chunk(tc);
     1086
     1087                if (unlikely(pool->object_count == 0)) {
    8621088                        talloc_abort("Pool object count zero!");
    8631089                        return 0;
    8641090                }
    8651091
    866                 *pool_object_count -= 1;
    867 
    868                 if (unlikely(*pool_object_count == 0)) {
    869                         TC_INVALIDATE_FULL_CHUNK(tc);
    870                         free(tc);
    871                 }
    872         } else if (tc->flags & TALLOC_FLAG_POOLMEM) {
     1092                pool->object_count--;
     1093
     1094                if (likely(pool->object_count != 0)) {
     1095                        return 0;
     1096                }
     1097
     1098                /*
     1099                 * With object_count==0, a pool becomes a normal piece of
     1100                 * memory to free. If it's allocated inside a pool, it needs
     1101                 * to be freed as poolmem, else it needs to be just freed.
     1102                */
     1103                ptr_to_free = pool;
     1104        } else {
     1105                ptr_to_free = tc;
     1106        }
     1107
     1108        if (tc->flags & TALLOC_FLAG_POOLMEM) {
    8731109                _talloc_free_poolmem(tc, location);
    874         } else {
    875                 TC_INVALIDATE_FULL_CHUNK(tc);
    876                 free(tc);
    877         }
     1110                return 0;
     1111        }
     1112
     1113        talloc_memlimit_update_on_free(tc);
     1114
     1115        TC_INVALIDATE_FULL_CHUNK(tc);
     1116        free(ptr_to_free);
    8781117        return 0;
    8791118}
    8801119
    881 /*
     1120static inline size_t _talloc_total_limit_size(const void *ptr,
     1121                                        struct talloc_memlimit *old_limit,
     1122                                        struct talloc_memlimit *new_limit);
     1123
     1124/*
    8821125   move a lump of memory from one talloc context to another return the
    8831126   ptr on success, or NULL if it could not be transferred.
     
    8871130{
    8881131        struct talloc_chunk *tc, *new_tc;
     1132        size_t ctx_size = 0;
    8891133
    8901134        if (unlikely(!ptr)) {
     
    8971141
    8981142        tc = talloc_chunk_from_ptr(ptr);
     1143
     1144        if (tc->limit != NULL) {
     1145
     1146                ctx_size = _talloc_total_limit_size(ptr, NULL, NULL);
     1147
     1148                /* Decrement the memory limit from the source .. */
     1149                talloc_memlimit_shrink(tc->limit->upper, ctx_size);
     1150
     1151                if (tc->limit->parent == tc) {
     1152                        tc->limit->upper = NULL;
     1153                } else {
     1154                        tc->limit = NULL;
     1155                }
     1156        }
    8991157
    9001158        if (unlikely(new_ctx == NULL)) {
     
    9081166                        if (tc->next) tc->next->prev = tc->prev;
    9091167                }
    910                
     1168
    9111169                tc->parent = tc->next = tc->prev = NULL;
    9121170                return discard_const_p(void, ptr);
     
    9341192        _TLIST_ADD(new_tc->child, tc);
    9351193
     1194        if (tc->limit || new_tc->limit) {
     1195                ctx_size = _talloc_total_limit_size(ptr, tc->limit,
     1196                                                    new_tc->limit);
     1197                /* .. and increment it in the destination. */
     1198                if (new_tc->limit) {
     1199                        talloc_memlimit_grow(new_tc->limit, ctx_size);
     1200                }
     1201        }
     1202
    9361203        return discard_const_p(void, ptr);
    9371204}
    9381205
    939 /* 
     1206/*
    9401207   move a lump of memory from one talloc context to another return the
    9411208   ptr on success, or NULL if it could not be transferred.
     
    9491216                return NULL;
    9501217        }
    951        
     1218
    9521219        tc = talloc_chunk_from_ptr(ptr);
    953        
     1220
    9541221        if (unlikely(tc->refs != NULL) && talloc_parent(ptr) != new_ctx) {
    9551222                struct talloc_reference_handle *h;
     
    9711238        }
    9721239#endif
    973        
     1240
    9741241        return _talloc_steal_internal(new_ctx, ptr);
    9751242}
    9761243
    977 /* 
     1244/*
    9781245   this is like a talloc_steal(), but you must supply the old
    9791246   parent. This resolves the ambiguity in a talloc_steal() which is
     
    10031270                        return discard_const_p(void, ptr);
    10041271                }
    1005         }       
     1272        }
    10061273
    10071274        /* it wasn't a parent */
     
    10401307/*
    10411308  remove a specific parent context from a pointer. This is a more
    1042   controlled varient of talloc_free()
     1309  controlled variant of talloc_free()
    10431310*/
    10441311_PUBLIC_ int talloc_unlink(const void *context, void *ptr)
    10451312{
    1046         struct talloc_chunk *tc_p, *new_p;
     1313        struct talloc_chunk *tc_p, *new_p, *tc_c;
    10471314        void *new_parent;
    10481315
     
    10591326        }
    10601327
    1061         if (context == NULL) {
    1062                 if (talloc_parent_chunk(ptr) != NULL) {
    1063                         return -1;
    1064                 }
     1328        if (context != NULL) {
     1329                tc_c = talloc_chunk_from_ptr(context);
    10651330        } else {
    1066                 if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) {
    1067                         return -1;
    1068                 }
    1069         }
    1070        
     1331                tc_c = NULL;
     1332        }
     1333        if (tc_c != talloc_parent_chunk(ptr)) {
     1334                return -1;
     1335        }
     1336
    10711337        tc_p = talloc_chunk_from_ptr(ptr);
    10721338
     
    11491415  return the name of a talloc ptr, or "UNNAMED"
    11501416*/
    1151 _PUBLIC_ const char *talloc_get_name(const void *ptr)
     1417static inline const char *__talloc_get_name(const void *ptr)
    11521418{
    11531419        struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
     
    11611427}
    11621428
     1429_PUBLIC_ const char *talloc_get_name(const void *ptr)
     1430{
     1431        return __talloc_get_name(ptr);
     1432}
    11631433
    11641434/*
     
    11701440        const char *pname;
    11711441        if (unlikely(ptr == NULL)) return NULL;
    1172         pname = talloc_get_name(ptr);
     1442        pname = __talloc_get_name(ptr);
    11731443        if (likely(pname == name || strcmp(pname, name) == 0)) {
    11741444                return discard_const_p(void, ptr);
     
    11771447}
    11781448
    1179 static void talloc_abort_type_missmatch(const char *location,
     1449static void talloc_abort_type_mismatch(const char *location,
    11801450                                        const char *name,
    11811451                                        const char *expected)
     
    12001470
    12011471        if (unlikely(ptr == NULL)) {
    1202                 talloc_abort_type_missmatch(location, NULL, name);
     1472                talloc_abort_type_mismatch(location, NULL, name);
    12031473                return NULL;
    12041474        }
    12051475
    1206         pname = talloc_get_name(ptr);
     1476        pname = __talloc_get_name(ptr);
    12071477        if (likely(pname == name || strcmp(pname, name) == 0)) {
    12081478                return discard_const_p(void, ptr);
    12091479        }
    12101480
    1211         talloc_abort_type_missmatch(location, pname, name);
     1481        talloc_abort_type_mismatch(location, pname, name);
    12121482        return NULL;
    12131483}
     
    12491519                void *child = TC_PTR_FROM_CHUNK(tc->child);
    12501520                const void *new_parent = null_context;
    1251                 struct talloc_chunk *old_parent = NULL;
    12521521                if (unlikely(tc->child->refs)) {
    12531522                        struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
     
    12551524                }
    12561525                if (unlikely(_talloc_free_internal(child, location) == -1)) {
     1526                        if (talloc_parent_chunk(child) != tc) {
     1527                                /*
     1528                                 * Destructor already reparented this child.
     1529                                 * No further reparenting needed.
     1530                                 */
     1531                                return;
     1532                        }
    12571533                        if (new_parent == null_context) {
    12581534                                struct talloc_chunk *p = talloc_parent_chunk(ptr);
     
    13051581}
    13061582
    1307 /* 
     1583/*
    13081584   Allocate a bit of memory as a child of an existing pointer
    13091585*/
     
    13311607}
    13321608
    1333 /* 
    1334    free a talloc pointer. This also frees all child pointers of this 
     1609/*
     1610   free a talloc pointer. This also frees all child pointers of this
    13351611   pointer recursively
    13361612
     
    13461622                return -1;
    13471623        }
    1348        
     1624
    13491625        tc = talloc_chunk_from_ptr(ptr);
    1350        
     1626
    13511627        if (unlikely(tc->refs != NULL)) {
    13521628                struct talloc_reference_handle *h;
     
    13681644                return -1;
    13691645        }
    1370        
     1646
    13711647        return _talloc_free_internal(ptr, location);
    13721648}
     
    13831659        void *new_ptr;
    13841660        bool malloced = false;
    1385         struct talloc_chunk *pool_tc = NULL;
     1661        struct talloc_pool_hdr *pool_hdr = NULL;
     1662        size_t old_size = 0;
     1663        size_t new_size = 0;
    13861664
    13871665        /* size zero is equivalent to free() */
     
    14121690        }
    14131691
    1414         /* don't let anybody try to realloc a talloc_pool */
     1692        if (tc->limit && (size > tc->size)) {
     1693                if (!talloc_memlimit_check(tc->limit, (size - tc->size))) {
     1694                        errno = ENOMEM;
     1695                        return NULL;
     1696                }
     1697        }
     1698
     1699        /* handle realloc inside a talloc_pool */
    14151700        if (unlikely(tc->flags & TALLOC_FLAG_POOLMEM)) {
    1416                 pool_tc = (struct talloc_chunk *)tc->pool;
     1701                pool_hdr = tc->pool;
    14171702        }
    14181703
    14191704#if (ALWAYS_REALLOC == 0)
    14201705        /* don't shrink if we have less than 1k to gain */
    1421         if (size < tc->size) {
    1422                 if (pool_tc) {
    1423                         void *next_tc = TC_POOLMEM_NEXT_CHUNK(tc);
     1706        if (size < tc->size && tc->limit == NULL) {
     1707                if (pool_hdr) {
     1708                        void *next_tc = tc_next_chunk(tc);
    14241709                        TC_INVALIDATE_SHRINK_CHUNK(tc, size);
    14251710                        tc->size = size;
    1426                         if (next_tc == pool_tc->pool) {
    1427                                 pool_tc->pool = TC_POOLMEM_NEXT_CHUNK(tc);
     1711                        if (next_tc == pool_hdr->end) {
     1712                                /* note: tc->size has changed, so this works */
     1713                                pool_hdr->end = tc_next_chunk(tc);
    14281714                        }
    14291715                        return ptr;
     
    14561742
    14571743#if ALWAYS_REALLOC
    1458         if (pool_tc) {
    1459                 new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
    1460                 *talloc_pool_objectcount(pool_tc) -= 1;
     1744        if (pool_hdr) {
     1745                new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE, 0);
     1746                pool_hdr->object_count--;
    14611747
    14621748                if (new_ptr == NULL) {
    14631749                        new_ptr = malloc(TC_HDR_SIZE+size);
    14641750                        malloced = true;
     1751                        new_size = size;
    14651752                }
    14661753
     
    14701757                }
    14711758        } else {
     1759                /* We're doing malloc then free here, so record the difference. */
     1760                old_size = tc->size;
     1761                new_size = size;
    14721762                new_ptr = malloc(size + TC_HDR_SIZE);
    14731763                if (new_ptr) {
     
    14771767        }
    14781768#else
    1479         if (pool_tc) {
    1480                 void *next_tc = TC_POOLMEM_NEXT_CHUNK(tc);
    1481                 size_t old_chunk_size = TC_POOLMEM_CHUNK_SIZE(tc);
     1769        if (pool_hdr) {
     1770                struct talloc_chunk *pool_tc;
     1771                void *next_tc = tc_next_chunk(tc);
     1772                size_t old_chunk_size = TC_ALIGN16(TC_HDR_SIZE + tc->size);
    14821773                size_t new_chunk_size = TC_ALIGN16(TC_HDR_SIZE + size);
    14831774                size_t space_needed;
    14841775                size_t space_left;
    1485                 unsigned int chunk_count = *talloc_pool_objectcount(pool_tc);
    1486 
     1776                unsigned int chunk_count = pool_hdr->object_count;
     1777
     1778                pool_tc = talloc_chunk_from_pool(pool_hdr);
    14871779                if (!(pool_tc->flags & TALLOC_FLAG_FREE)) {
    14881780                        chunk_count -= 1;
     
    14941786                         * chunk in the pool.
    14951787                         */
     1788                        char *start = tc_pool_first_chunk(pool_hdr);
    14961789                        space_needed = new_chunk_size;
    1497                         space_left = pool_tc->size - TALLOC_POOL_HDR_SIZE;
     1790                        space_left = (char *)tc_pool_end(pool_hdr) - start;
    14981791
    14991792                        if (space_left >= space_needed) {
    15001793                                size_t old_used = TC_HDR_SIZE + tc->size;
    15011794                                size_t new_used = TC_HDR_SIZE + size;
    1502                                 pool_tc->pool = TC_POOL_FIRST_CHUNK(pool_tc);
     1795                                new_ptr = start;
     1796
    15031797#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
    1504                                 /*
    1505                                  * we need to prepare the memmove into
    1506                                  * the unaccessable area.
    1507                                  */
    15081798                                {
    1509                                         size_t diff = PTR_DIFF(tc, pool_tc->pool);
    1510                                         size_t flen = MIN(diff, old_used);
    1511                                         char *fptr = (char *)pool_tc->pool;
    1512                                         VALGRIND_MAKE_MEM_UNDEFINED(fptr, flen);
     1799                                        /*
     1800                                         * The area from
     1801                                         * start -> tc may have
     1802                                         * been freed and thus been marked as
     1803                                         * VALGRIND_MEM_NOACCESS. Set it to
     1804                                         * VALGRIND_MEM_UNDEFINED so we can
     1805                                         * copy into it without valgrind errors.
     1806                                         * We can't just mark
     1807                                         * new_ptr -> new_ptr + old_used
     1808                                         * as this may overlap on top of tc,
     1809                                         * (which is why we use memmove, not
     1810                                         * memcpy below) hence the MIN.
     1811                                         */
     1812                                        size_t undef_len = MIN((((char *)tc) - ((char *)new_ptr)),old_used);
     1813                                        VALGRIND_MAKE_MEM_UNDEFINED(new_ptr, undef_len);
    15131814                                }
    15141815#endif
    1515                                 memmove(pool_tc->pool, tc, old_used);
    1516                                 new_ptr = pool_tc->pool;
     1816
     1817                                memmove(new_ptr, tc, old_used);
    15171818
    15181819                                tc = (struct talloc_chunk *)new_ptr;
     
    15241825                                 * too.
    15251826                                 */
    1526                                 pool_tc->pool = new_used + (char *)new_ptr;
    1527                                 TC_INVALIDATE_POOL(pool_tc);
     1827                                pool_hdr->end = new_used + (char *)new_ptr;
     1828                                tc_invalidate_pool(pool_hdr);
    15281829
    15291830                                /* now the aligned pointer */
    1530                                 pool_tc->pool = new_chunk_size + (char *)new_ptr;
     1831                                pool_hdr->end = new_chunk_size + (char *)new_ptr;
    15311832                                goto got_new_ptr;
    15321833                        }
     
    15421843                }
    15431844
    1544                 if (next_tc == pool_tc->pool) {
     1845                if (next_tc == pool_hdr->end) {
    15451846                        /*
    15461847                         * optimize for the case where 'tc' is the last
     
    15481849                         */
    15491850                        space_needed = new_chunk_size - old_chunk_size;
    1550                         space_left = TC_POOL_SPACE_LEFT(pool_tc);
     1851                        space_left = tc_pool_space_left(pool_hdr);
    15511852
    15521853                        if (space_left >= space_needed) {
     
    15541855                                tc->flags &= ~TALLOC_FLAG_FREE;
    15551856                                tc->size = size;
    1556                                 pool_tc->pool = TC_POOLMEM_NEXT_CHUNK(tc);
     1857                                pool_hdr->end = tc_next_chunk(tc);
    15571858                                return ptr;
    15581859                        }
    15591860                }
    15601861
    1561                 new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
     1862                new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE, 0);
    15621863
    15631864                if (new_ptr == NULL) {
    15641865                        new_ptr = malloc(TC_HDR_SIZE+size);
    15651866                        malloced = true;
     1867                        new_size = size;
    15661868                }
    15671869
     
    15731875        }
    15741876        else {
     1877                /* We're doing realloc here, so record the difference. */
     1878                old_size = tc->size;
     1879                new_size = size;
    15751880                new_ptr = realloc(tc, size + TC_HDR_SIZE);
    15761881        }
    15771882got_new_ptr:
    15781883#endif
    1579         if (unlikely(!new_ptr)) {       
    1580                 tc->flags &= ~TALLOC_FLAG_FREE; 
    1581                 return NULL; 
     1884        if (unlikely(!new_ptr)) {
     1885                tc->flags &= ~TALLOC_FLAG_FREE;
     1886                return NULL;
    15821887        }
    15831888
     
    16011906        }
    16021907
     1908        if (new_size > old_size) {
     1909                talloc_memlimit_grow(tc->limit, new_size - old_size);
     1910        } else if (new_size < old_size) {
     1911                talloc_memlimit_shrink(tc->limit, old_size - new_size);
     1912        }
     1913
    16031914        tc->size = size;
    16041915        _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
     
    16191930}
    16201931
    1621 /*
    1622   return the total size of a talloc pool (subtree)
    1623 */
    1624 _PUBLIC_ size_t talloc_total_size(const void *ptr)
     1932enum talloc_mem_count_type {
     1933        TOTAL_MEM_SIZE,
     1934        TOTAL_MEM_BLOCKS,
     1935        TOTAL_MEM_LIMIT,
     1936};
     1937
     1938static inline size_t _talloc_total_mem_internal(const void *ptr,
     1939                                         enum talloc_mem_count_type type,
     1940                                         struct talloc_memlimit *old_limit,
     1941                                         struct talloc_memlimit *new_limit)
    16251942{
    16261943        size_t total = 0;
     
    16361953        tc = talloc_chunk_from_ptr(ptr);
    16371954
     1955        if (old_limit || new_limit) {
     1956                if (tc->limit && tc->limit->upper == old_limit) {
     1957                        tc->limit->upper = new_limit;
     1958                }
     1959        }
     1960
     1961        /* optimize in the memlimits case */
     1962        if (type == TOTAL_MEM_LIMIT &&
     1963            tc->limit != NULL &&
     1964            tc->limit != old_limit &&
     1965            tc->limit->parent == tc) {
     1966                return tc->limit->cur_size;
     1967        }
     1968
    16381969        if (tc->flags & TALLOC_FLAG_LOOP) {
    16391970                return 0;
     
    16421973        tc->flags |= TALLOC_FLAG_LOOP;
    16431974
    1644         if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) {
    1645                 total = tc->size;
    1646         }
    1647         for (c=tc->child;c;c=c->next) {
    1648                 total += talloc_total_size(TC_PTR_FROM_CHUNK(c));
     1975        if (old_limit || new_limit) {
     1976                if (old_limit == tc->limit) {
     1977                        tc->limit = new_limit;
     1978                }
     1979        }
     1980
     1981        switch (type) {
     1982        case TOTAL_MEM_SIZE:
     1983                if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) {
     1984                        total = tc->size;
     1985                }
     1986                break;
     1987        case TOTAL_MEM_BLOCKS:
     1988                total++;
     1989                break;
     1990        case TOTAL_MEM_LIMIT:
     1991                if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) {
     1992                        /*
     1993                         * Don't count memory allocated from a pool
     1994                         * when calculating limits. Only count the
     1995                         * pool itself.
     1996                         */
     1997                        if (!(tc->flags & TALLOC_FLAG_POOLMEM)) {
     1998                                if (tc->flags & TALLOC_FLAG_POOL) {
     1999                                        /*
     2000                                         * If this is a pool, the allocated
     2001                                         * size is in the pool header, and
     2002                                         * remember to add in the prefix
     2003                                         * length.
     2004                                         */
     2005                                        struct talloc_pool_hdr *pool_hdr
     2006                                                        = talloc_pool_from_chunk(tc);
     2007                                        total = pool_hdr->poolsize +
     2008                                                        TC_HDR_SIZE +
     2009                                                        TP_HDR_SIZE;
     2010                                } else {
     2011                                        total = tc->size + TC_HDR_SIZE;
     2012                                }
     2013                        }
     2014                }
     2015                break;
     2016        }
     2017        for (c = tc->child; c; c = c->next) {
     2018                total += _talloc_total_mem_internal(TC_PTR_FROM_CHUNK(c), type,
     2019                                                    old_limit, new_limit);
    16492020        }
    16502021
     
    16552026
    16562027/*
     2028  return the total size of a talloc pool (subtree)
     2029*/
     2030_PUBLIC_ size_t talloc_total_size(const void *ptr)
     2031{
     2032        return _talloc_total_mem_internal(ptr, TOTAL_MEM_SIZE, NULL, NULL);
     2033}
     2034
     2035/*
    16572036  return the total number of blocks in a talloc pool (subtree)
    16582037*/
    16592038_PUBLIC_ size_t talloc_total_blocks(const void *ptr)
    16602039{
    1661         size_t total = 0;
    1662         struct talloc_chunk *c, *tc;
    1663 
    1664         if (ptr == NULL) {
    1665                 ptr = null_context;
    1666         }
    1667         if (ptr == NULL) {
    1668                 return 0;
    1669         }
    1670 
    1671         tc = talloc_chunk_from_ptr(ptr);
    1672 
    1673         if (tc->flags & TALLOC_FLAG_LOOP) {
    1674                 return 0;
    1675         }
    1676 
    1677         tc->flags |= TALLOC_FLAG_LOOP;
    1678 
    1679         total++;
    1680         for (c=tc->child;c;c=c->next) {
    1681                 total += talloc_total_blocks(TC_PTR_FROM_CHUNK(c));
    1682         }
    1683 
    1684         tc->flags &= ~TALLOC_FLAG_LOOP;
    1685 
    1686         return total;
     2040        return _talloc_total_mem_internal(ptr, TOTAL_MEM_BLOCKS, NULL, NULL);
    16872041}
    16882042
     
    17452099static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f)
    17462100{
    1747         const char *name = talloc_get_name(ptr);
     2101        const char *name = __talloc_get_name(ptr);
     2102        struct talloc_chunk *tc;
    17482103        FILE *f = (FILE *)_f;
    17492104
     
    17532108        }
    17542109
     2110        tc = talloc_chunk_from_ptr(ptr);
     2111        if (tc->limit && tc->limit->parent == tc) {
     2112                fprintf(f, "%*s%-30s is a memlimit context"
     2113                        " (max_size = %lu bytes, cur_size = %lu bytes)\n",
     2114                        depth*4, "",
     2115                        name,
     2116                        (unsigned long)tc->limit->max_size,
     2117                        (unsigned long)tc->limit->cur_size);
     2118        }
     2119
    17552120        if (depth == 0) {
    1756                 fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n", 
     2121                fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n",
    17572122                        (max_depth < 0 ? "full " :""), name,
    17582123                        (unsigned long)talloc_total_size(ptr),
     
    17612126        }
    17622127
    1763         fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n", 
     2128        fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n",
    17642129                depth*4, "",
    17652130                name,
     
    19002265}
    19012266
    1902 /* 
    1903    talloc and zero memory. 
     2267/*
     2268   talloc and zero memory.
    19042269*/
    19052270_PUBLIC_ void *_talloc_zero(const void *ctx, size_t size, const char *name)
     
    19152280
    19162281/*
    1917   memdup with a talloc. 
     2282  memdup with a talloc.
    19182283*/
    19192284_PUBLIC_ void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
     
    20222387{
    20232388        if (unlikely(!s)) {
    2024                 return talloc_strdup(NULL, a);
     2389                return talloc_strndup(NULL, a, n);
    20252390        }
    20262391
     
    20412406
    20422407        if (unlikely(!s)) {
    2043                 return talloc_strdup(NULL, a);
     2408                return talloc_strndup(NULL, a, n);
    20442409        }
    20452410
     
    20692434        char *ret;
    20702435        va_list ap2;
    2071         char c;
     2436        char buf[1024];
    20722437
    20732438        /* this call looks strange, but it makes it work on older solaris boxes */
    20742439        va_copy(ap2, ap);
    2075         len = vsnprintf(&c, 1, fmt, ap2);
     2440        len = vsnprintf(buf, sizeof(buf), fmt, ap2);
    20762441        va_end(ap2);
    20772442        if (unlikely(len < 0)) {
     
    20822447        if (unlikely(!ret)) return NULL;
    20832448
    2084         va_copy(ap2, ap);
    2085         vsnprintf(ret, len+1, fmt, ap2);
    2086         va_end(ap2);
     2449        if (len < sizeof(buf)) {
     2450                memcpy(ret, buf, len+1);
     2451        } else {
     2452                va_copy(ap2, ap);
     2453                vsnprintf(ret, len+1, fmt, ap2);
     2454                va_end(ap2);
     2455        }
    20872456
    20882457        _talloc_set_name_const(ret, ret);
     
    23302699
    23312700        tc = talloc_chunk_from_ptr(context);
    2332         fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
     2701        fprintf(file, "talloc parents of '%s'\n", __talloc_get_name(context));
    23332702        while (tc) {
    2334                 fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
     2703                fprintf(file, "\t'%s'\n", __talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
    23352704                while (tc && tc->prev) tc = tc->prev;
    23362705                if (tc) {
     
    23532722
    23542723        tc = talloc_chunk_from_ptr(context);
    2355         while (tc && depth > 0) {
     2724        while (tc) {
     2725                if (depth <= 0) {
     2726                        return 0;
     2727                }
    23562728                if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
    23572729                while (tc && tc->prev) tc = tc->prev;
     
    23712743        return _talloc_is_parent(context, ptr, TALLOC_MAX_DEPTH);
    23722744}
     2745
     2746/*
     2747  return the total size of memory used by this context and all children
     2748*/
     2749static inline size_t _talloc_total_limit_size(const void *ptr,
     2750                                        struct talloc_memlimit *old_limit,
     2751                                        struct talloc_memlimit *new_limit)
     2752{
     2753        return _talloc_total_mem_internal(ptr, TOTAL_MEM_LIMIT,
     2754                                          old_limit, new_limit);
     2755}
     2756
     2757static inline bool talloc_memlimit_check(struct talloc_memlimit *limit, size_t size)
     2758{
     2759        struct talloc_memlimit *l;
     2760
     2761        for (l = limit; l != NULL; l = l->upper) {
     2762                if (l->max_size != 0 &&
     2763                    ((l->max_size <= l->cur_size) ||
     2764                     (l->max_size - l->cur_size < size))) {
     2765                        return false;
     2766                }
     2767        }
     2768
     2769        return true;
     2770}
     2771
     2772/*
     2773  Update memory limits when freeing a talloc_chunk.
     2774*/
     2775static void talloc_memlimit_update_on_free(struct talloc_chunk *tc)
     2776{
     2777        size_t limit_shrink_size;
     2778
     2779        if (!tc->limit) {
     2780                return;
     2781        }
     2782
     2783        /*
     2784         * Pool entries don't count. Only the pools
     2785         * themselves are counted as part of the memory
     2786         * limits. Note that this also takes care of
     2787         * nested pools which have both flags
     2788         * TALLOC_FLAG_POOLMEM|TALLOC_FLAG_POOL set.
     2789         */
     2790        if (tc->flags & TALLOC_FLAG_POOLMEM) {
     2791                return;
     2792        }
     2793
     2794        /*
     2795         * If we are part of a memory limited context hierarchy
     2796         * we need to subtract the memory used from the counters
     2797         */
     2798
     2799        limit_shrink_size = tc->size+TC_HDR_SIZE;
     2800
     2801        /*
     2802         * If we're deallocating a pool, take into
     2803         * account the prefix size added for the pool.
     2804         */
     2805
     2806        if (tc->flags & TALLOC_FLAG_POOL) {
     2807                limit_shrink_size += TP_HDR_SIZE;
     2808        }
     2809
     2810        talloc_memlimit_shrink(tc->limit, limit_shrink_size);
     2811
     2812        if (tc->limit->parent == tc) {
     2813                free(tc->limit);
     2814        }
     2815
     2816        tc->limit = NULL;
     2817}
     2818
     2819/*
     2820  Increase memory limit accounting after a malloc/realloc.
     2821*/
     2822static void talloc_memlimit_grow(struct talloc_memlimit *limit,
     2823                                size_t size)
     2824{
     2825        struct talloc_memlimit *l;
     2826
     2827        for (l = limit; l != NULL; l = l->upper) {
     2828                size_t new_cur_size = l->cur_size + size;
     2829                if (new_cur_size < l->cur_size) {
     2830                        talloc_abort("logic error in talloc_memlimit_grow\n");
     2831                        return;
     2832                }
     2833                l->cur_size = new_cur_size;
     2834        }
     2835}
     2836
     2837/*
     2838  Decrease memory limit accounting after a free/realloc.
     2839*/
     2840static void talloc_memlimit_shrink(struct talloc_memlimit *limit,
     2841                                size_t size)
     2842{
     2843        struct talloc_memlimit *l;
     2844
     2845        for (l = limit; l != NULL; l = l->upper) {
     2846                if (l->cur_size < size) {
     2847                        talloc_abort("logic error in talloc_memlimit_shrink\n");
     2848                        return;
     2849                }
     2850                l->cur_size = l->cur_size - size;
     2851        }
     2852}
     2853
     2854_PUBLIC_ int talloc_set_memlimit(const void *ctx, size_t max_size)
     2855{
     2856        struct talloc_chunk *tc = talloc_chunk_from_ptr(ctx);
     2857        struct talloc_memlimit *orig_limit;
     2858        struct talloc_memlimit *limit = NULL;
     2859
     2860        if (tc->limit && tc->limit->parent == tc) {
     2861                tc->limit->max_size = max_size;
     2862                return 0;
     2863        }
     2864        orig_limit = tc->limit;
     2865
     2866        limit = malloc(sizeof(struct talloc_memlimit));
     2867        if (limit == NULL) {
     2868                return 1;
     2869        }
     2870        limit->parent = tc;
     2871        limit->max_size = max_size;
     2872        limit->cur_size = _talloc_total_limit_size(ctx, tc->limit, limit);
     2873
     2874        if (orig_limit) {
     2875                limit->upper = orig_limit;
     2876        } else {
     2877                limit->upper = NULL;
     2878        }
     2879
     2880        return 0;
     2881}
Note: See TracChangeset for help on using the changeset viewer.