media/libvpx/vpx_mem/vpx_mem.c

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /*
     2  *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
     3  *
     4  *  Use of this source code is governed by a BSD-style license
     5  *  that can be found in the LICENSE file in the root of the source
     6  *  tree. An additional intellectual property rights grant can be found
     7  *  in the file PATENTS.  All contributing project authors may
     8  *  be found in the AUTHORS file in the root of the source tree.
     9  */
    12 #define __VPX_MEM_C__
    14 #include "vpx_mem.h"
    15 #include <stdio.h>
    16 #include <stdlib.h>
    17 #include <string.h>
    18 #include "include/vpx_mem_intrnl.h"
    20 #if CONFIG_MEM_TRACKER
    21 #ifndef VPX_NO_GLOBALS
    22 static unsigned long g_alloc_count = 0;
    23 #else
    24 #include "vpx_global_handling.h"
    25 #define g_alloc_count vpxglobalm(vpxmem,g_alloc_count)
    26 #endif
    27 #endif
    29 #if CONFIG_MEM_MANAGER
    30 # include "heapmm.h"
    31 # include "hmm_intrnl.h"
    33 # define SHIFT_HMM_ADDR_ALIGN_UNIT 5
    34 # define TOTAL_MEMORY_TO_ALLOCATE  20971520 /* 20 * 1024 * 1024 */
    36 # define MM_DYNAMIC_MEMORY 1
    37 # if MM_DYNAMIC_MEMORY
    38 static unsigned char *g_p_mng_memory_raw = NULL;
    39 static unsigned char *g_p_mng_memory     = NULL;
    40 # else
    41 static unsigned char g_p_mng_memory[TOTAL_MEMORY_TO_ALLOCATE];
    42 # endif
    44 static size_t g_mm_memory_size = TOTAL_MEMORY_TO_ALLOCATE;
    46 static hmm_descriptor hmm_d;
    47 static int g_mng_memory_allocated = 0;
    49 static int vpx_mm_create_heap_memory();
    50 static void *vpx_mm_realloc(void *memblk, size_t size);
    51 #endif /*CONFIG_MEM_MANAGER*/
    53 #if USE_GLOBAL_FUNCTION_POINTERS
    54 struct GLOBAL_FUNC_POINTERS {
    55   g_malloc_func g_malloc;
    56   g_calloc_func g_calloc;
    57   g_realloc_func g_realloc;
    58   g_free_func g_free;
    59   g_memcpy_func g_memcpy;
    60   g_memset_func g_memset;
    61   g_memmove_func g_memmove;
    62 } *g_func = NULL;
    64 # define VPX_MALLOC_L  g_func->g_malloc
    65 # define VPX_REALLOC_L g_func->g_realloc
    66 # define VPX_FREE_L    g_func->g_free
    67 # define VPX_MEMCPY_L  g_func->g_memcpy
    68 # define VPX_MEMSET_L  g_func->g_memset
    69 # define VPX_MEMMOVE_L g_func->g_memmove
    70 #else
    71 # define VPX_MALLOC_L  malloc
    72 # define VPX_REALLOC_L realloc
    73 # define VPX_FREE_L    free
    74 # define VPX_MEMCPY_L  memcpy
    75 # define VPX_MEMSET_L  memset
    76 # define VPX_MEMMOVE_L memmove
    77 #endif /* USE_GLOBAL_FUNCTION_POINTERS */
    79 unsigned int vpx_mem_get_version() {
    80   unsigned int ver = ((unsigned int)(unsigned char)VPX_MEM_VERSION_CHIEF << 24 |
    81                       (unsigned int)(unsigned char)VPX_MEM_VERSION_MAJOR << 16 |
    82                       (unsigned int)(unsigned char)VPX_MEM_VERSION_MINOR << 8  |
    83                       (unsigned int)(unsigned char)VPX_MEM_VERSION_PATCH);
    84   return ver;
    85 }
    87 int vpx_mem_set_heap_size(size_t size) {
    88   int ret = -1;
    90 #if CONFIG_MEM_MANAGER
    91 #if MM_DYNAMIC_MEMORY
    93   if (!g_mng_memory_allocated && size) {
    94     g_mm_memory_size = size;
    95     ret = 0;
    96   } else
    97     ret = -3;
    99 #else
   100   ret = -2;
   101 #endif
   102 #else
   103   (void)size;
   104 #endif
   106   return ret;
   107 }
   109 void *vpx_memalign(size_t align, size_t size) {
   110   void *addr,
   111        * x = NULL;
   113 #if CONFIG_MEM_MANAGER
   114   int number_aau;
   116   if (vpx_mm_create_heap_memory() < 0) {
   117     _P(printf("[vpx][mm] ERROR vpx_memalign() Couldn't create memory for Heap.\n");)
   118   }
   120   number_aau = ((size + align - 1 + ADDRESS_STORAGE_SIZE) >>
   121                 SHIFT_HMM_ADDR_ALIGN_UNIT) + 1;
   123   addr = hmm_alloc(&hmm_d, number_aau);
   124 #else
   125   addr = VPX_MALLOC_L(size + align - 1 + ADDRESS_STORAGE_SIZE);
   126 #endif /*CONFIG_MEM_MANAGER*/
   128   if (addr) {
   129     x = align_addr((unsigned char *)addr + ADDRESS_STORAGE_SIZE, (int)align);
   130     /* save the actual malloc address */
   131     ((size_t *)x)[-1] = (size_t)addr;
   132   }
   134   return x;
   135 }
   137 void *vpx_malloc(size_t size) {
   138   return vpx_memalign(DEFAULT_ALIGNMENT, size);
   139 }
   141 void *vpx_calloc(size_t num, size_t size) {
   142   void *x;
   144   x = vpx_memalign(DEFAULT_ALIGNMENT, num * size);
   146   if (x)
   147     VPX_MEMSET_L(x, 0, num * size);
   149   return x;
   150 }
   152 void *vpx_realloc(void *memblk, size_t size) {
   153   void *addr,
   154        * new_addr = NULL;
   155   int align = DEFAULT_ALIGNMENT;
   157   /*
   158   The realloc() function changes the size of the object pointed to by
   159   ptr to the size specified by size, and returns a pointer to the
   160   possibly moved block. The contents are unchanged up to the lesser
   161   of the new and old sizes. If ptr is null, realloc() behaves like
   162   malloc() for the specified size. If size is zero (0) and ptr is
   163   not a null pointer, the object pointed to is freed.
   164   */
   165   if (!memblk)
   166     new_addr = vpx_malloc(size);
   167   else if (!size)
   168     vpx_free(memblk);
   169   else {
   170     addr   = (void *)(((size_t *)memblk)[-1]);
   171     memblk = NULL;
   173 #if CONFIG_MEM_MANAGER
   174     new_addr = vpx_mm_realloc(addr, size + align + ADDRESS_STORAGE_SIZE);
   175 #else
   176     new_addr = VPX_REALLOC_L(addr, size + align + ADDRESS_STORAGE_SIZE);
   177 #endif
   179     if (new_addr) {
   180       addr = new_addr;
   181       new_addr = (void *)(((size_t)
   182                            ((unsigned char *)new_addr + ADDRESS_STORAGE_SIZE) + (align - 1)) &
   183                           (size_t) - align);
   184       /* save the actual malloc address */
   185       ((size_t *)new_addr)[-1] = (size_t)addr;
   186     }
   187   }
   189   return new_addr;
   190 }
   192 void vpx_free(void *memblk) {
   193   if (memblk) {
   194     void *addr = (void *)(((size_t *)memblk)[-1]);
   195 #if CONFIG_MEM_MANAGER
   196     hmm_free(&hmm_d, addr);
   197 #else
   198     VPX_FREE_L(addr);
   199 #endif
   200   }
   201 }
   203 #if CONFIG_MEM_TRACKER
   204 void *xvpx_memalign(size_t align, size_t size, char *file, int line) {
   205 #if TRY_BOUNDS_CHECK
   206   unsigned char *x_bounds;
   207 #endif
   209   void *x;
   211   if (g_alloc_count == 0) {
   212 #if TRY_BOUNDS_CHECK
   213     int i_rv = vpx_memory_tracker_init(BOUNDS_CHECK_PAD_SIZE, BOUNDS_CHECK_VALUE);
   214 #else
   215     int i_rv = vpx_memory_tracker_init(0, 0);
   216 #endif
   218     if (i_rv < 0) {
   219       _P(printf("ERROR xvpx_malloc MEM_TRACK_USAGE error vpx_memory_tracker_init().\n");)
   220     }
   221   }
   223 #if TRY_BOUNDS_CHECK
   224   {
   225     int i;
   226     unsigned int tempme = BOUNDS_CHECK_VALUE;
   228     x_bounds = vpx_memalign(align, size + (BOUNDS_CHECK_PAD_SIZE * 2));
   230     if (x_bounds) {
   231       /*we're aligning the address twice here but to keep things
   232         consistent we want to have the padding come before the stored
   233         address so no matter what free function gets called we will
   234         attempt to free the correct address*/
   235       x_bounds = (unsigned char *)(((size_t *)x_bounds)[-1]);
   236       x = align_addr(x_bounds + BOUNDS_CHECK_PAD_SIZE + ADDRESS_STORAGE_SIZE,
   237                      (int)align);
   238       /* save the actual malloc address */
   239       ((size_t *)x)[-1] = (size_t)x_bounds;
   241       for (i = 0; i < BOUNDS_CHECK_PAD_SIZE; i += sizeof(unsigned int)) {
   242         VPX_MEMCPY_L(x_bounds + i, &tempme, sizeof(unsigned int));
   243         VPX_MEMCPY_L((unsigned char *)x + size + i,
   244                      &tempme, sizeof(unsigned int));
   245       }
   246     } else
   247       x = NULL;
   248   }
   249 #else
   250   x = vpx_memalign(align, size);
   251 #endif /*TRY_BOUNDS_CHECK*/
   253   g_alloc_count++;
   255   vpx_memory_tracker_add((size_t)x, (unsigned int)size, file, line, 1);
   257   return x;
   258 }
   260 void *xvpx_malloc(size_t size, char *file, int line) {
   261   return xvpx_memalign(DEFAULT_ALIGNMENT, size, file, line);
   262 }
   264 void *xvpx_calloc(size_t num, size_t size, char *file, int line) {
   265   void *x = xvpx_memalign(DEFAULT_ALIGNMENT, num * size, file, line);
   267   if (x)
   268     VPX_MEMSET_L(x, 0, num * size);
   270   return x;
   271 }
   273 void *xvpx_realloc(void *memblk, size_t size, char *file, int line) {
   274   struct mem_block *p = NULL;
   275   int orig_size = 0,
   276       orig_line = 0;
   277   char *orig_file = NULL;
   279 #if TRY_BOUNDS_CHECK
   280   unsigned char *x_bounds = memblk ?
   281                             (unsigned char *)(((size_t *)memblk)[-1]) :
   282                             NULL;
   283 #endif
   285   void *x;
   287   if (g_alloc_count == 0) {
   288 #if TRY_BOUNDS_CHECK
   290     if (!vpx_memory_tracker_init(BOUNDS_CHECK_PAD_SIZE, BOUNDS_CHECK_VALUE))
   291 #else
   292     if (!vpx_memory_tracker_init(0, 0))
   293 #endif
   294     {
   295       _P(printf("ERROR xvpx_malloc MEM_TRACK_USAGE error vpx_memory_tracker_init().\n");)
   296     }
   297   }
   299   if ((p = vpx_memory_tracker_find((size_t)memblk))) {
   300     orig_size = p->size;
   301     orig_file = p->file;
   302     orig_line = p->line;
   303   }
   305 #if TRY_BOUNDS_CHECK_ON_FREE
   306   vpx_memory_tracker_check_integrity(file, line);
   307 #endif
   309   /* have to do this regardless of success, because
   310    * the memory that does get realloc'd may change
   311    * the bounds values of this block
   312    */
   313   vpx_memory_tracker_remove((size_t)memblk);
   315 #if TRY_BOUNDS_CHECK
   316   {
   317     int i;
   318     unsigned int tempme = BOUNDS_CHECK_VALUE;
   320     x_bounds = vpx_realloc(memblk, size + (BOUNDS_CHECK_PAD_SIZE * 2));
   322     if (x_bounds) {
   323       x_bounds = (unsigned char *)(((size_t *)x_bounds)[-1]);
   324       x = align_addr(x_bounds + BOUNDS_CHECK_PAD_SIZE + ADDRESS_STORAGE_SIZE,
   325                      (int)DEFAULT_ALIGNMENT);
   326       /* save the actual malloc address */
   327       ((size_t *)x)[-1] = (size_t)x_bounds;
   329       for (i = 0; i < BOUNDS_CHECK_PAD_SIZE; i += sizeof(unsigned int)) {
   330         VPX_MEMCPY_L(x_bounds + i, &tempme, sizeof(unsigned int));
   331         VPX_MEMCPY_L((unsigned char *)x + size + i,
   332                      &tempme, sizeof(unsigned int));
   333       }
   334     } else
   335       x = NULL;
   336   }
   337 #else
   338   x = vpx_realloc(memblk, size);
   339 #endif /*TRY_BOUNDS_CHECK*/
   341   if (!memblk) ++g_alloc_count;
   343   if (x)
   344     vpx_memory_tracker_add((size_t)x, (unsigned int)size, file, line, 1);
   345   else
   346     vpx_memory_tracker_add((size_t)memblk, orig_size, orig_file, orig_line, 1);
   348   return x;
   349 }
   351 void xvpx_free(void *p_address, char *file, int line) {
   352 #if TRY_BOUNDS_CHECK
   353   unsigned char *p_bounds_address = (unsigned char *)p_address;
   354   /*p_bounds_address -= BOUNDS_CHECK_PAD_SIZE;*/
   355 #endif
   357 #if !TRY_BOUNDS_CHECK_ON_FREE
   358   (void)file;
   359   (void)line;
   360 #endif
   362   if (p_address) {
   363 #if TRY_BOUNDS_CHECK_ON_FREE
   364     vpx_memory_tracker_check_integrity(file, line);
   365 #endif
   367     /* if the addr isn't found in the list, assume it was allocated via
   368      * vpx_ calls not xvpx_, therefore it does not contain any padding
   369      */
   370     if (vpx_memory_tracker_remove((size_t)p_address) == -2) {
   371       p_bounds_address = p_address;
   372       _P(fprintf(stderr, "[vpx_mem][xvpx_free] addr: %p not found in"
   373                  " list; freed from file:%s"
   374                  " line:%d\n", p_address, file, line));
   375     } else
   376       --g_alloc_count;
   378 #if TRY_BOUNDS_CHECK
   379     vpx_free(p_bounds_address);
   380 #else
   381     vpx_free(p_address);
   382 #endif
   384     if (!g_alloc_count)
   385       vpx_memory_tracker_destroy();
   386   }
   387 }
   389 #endif /*CONFIG_MEM_TRACKER*/
   391 #if CONFIG_MEM_CHECKS
   392 #if defined(VXWORKS)
   393 #include <task_lib.h> /*for task_delay()*/
   394 /* This function is only used to get a stack trace of the player
   395 object so we can se where we are having a problem. */
   396 static int get_my_tt(int task) {
   397   tt(task);
   399   return 0;
   400 }
   402 static void vx_sleep(int msec) {
   403   int ticks_to_sleep = 0;
   405   if (msec) {
   406     int msec_per_tick = 1000 / sys_clk_rate_get();
   408     if (msec < msec_per_tick)
   409       ticks_to_sleep++;
   410     else
   411       ticks_to_sleep = msec / msec_per_tick;
   412   }
   414   task_delay(ticks_to_sleep);
   415 }
   416 #endif
   417 #endif
   419 void *vpx_memcpy(void *dest, const void *source, size_t length) {
   420 #if CONFIG_MEM_CHECKS
   422   if (((int)dest < 0x4000) || ((int)source < 0x4000)) {
   423     _P(printf("WARNING: vpx_memcpy dest:0x%x source:0x%x len:%d\n", (int)dest, (int)source, length);)
   425 #if defined(VXWORKS)
   426     sp(get_my_tt, task_id_self(), 0, 0, 0, 0, 0, 0, 0, 0);
   428     vx_sleep(10000);
   429 #endif
   430   }
   432 #endif
   434   return VPX_MEMCPY_L(dest, source, length);
   435 }
   437 void *vpx_memset(void *dest, int val, size_t length) {
   438 #if CONFIG_MEM_CHECKS
   440   if ((int)dest < 0x4000) {
   441     _P(printf("WARNING: vpx_memset dest:0x%x val:%d len:%d\n", (int)dest, val, length);)
   443 #if defined(VXWORKS)
   444     sp(get_my_tt, task_id_self(), 0, 0, 0, 0, 0, 0, 0, 0);
   446     vx_sleep(10000);
   447 #endif
   448   }
   450 #endif
   452   return VPX_MEMSET_L(dest, val, length);
   453 }
   455 void *vpx_memmove(void *dest, const void *src, size_t count) {
   456 #if CONFIG_MEM_CHECKS
   458   if (((int)dest < 0x4000) || ((int)src < 0x4000)) {
   459     _P(printf("WARNING: vpx_memmove dest:0x%x src:0x%x count:%d\n", (int)dest, (int)src, count);)
   461 #if defined(VXWORKS)
   462     sp(get_my_tt, task_id_self(), 0, 0, 0, 0, 0, 0, 0, 0);
   464     vx_sleep(10000);
   465 #endif
   466   }
   468 #endif
   470   return VPX_MEMMOVE_L(dest, src, count);
   471 }
   473 #if CONFIG_MEM_MANAGER
   475 static int vpx_mm_create_heap_memory() {
   476   int i_rv = 0;
   478   if (!g_mng_memory_allocated) {
   479 #if MM_DYNAMIC_MEMORY
   480     g_p_mng_memory_raw =
   481       (unsigned char *)malloc(g_mm_memory_size + HMM_ADDR_ALIGN_UNIT);
   483     if (g_p_mng_memory_raw) {
   484       g_p_mng_memory = (unsigned char *)((((unsigned int)g_p_mng_memory_raw) +
   485                                           HMM_ADDR_ALIGN_UNIT - 1) &
   486                                          -(int)HMM_ADDR_ALIGN_UNIT);
   488       _P(printf("[vpx][mm] total memory size:%d g_p_mng_memory_raw:0x%x g_p_mng_memory:0x%x\n"
   489 , g_mm_memory_size + HMM_ADDR_ALIGN_UNIT
   490 , (unsigned int)g_p_mng_memory_raw
   491 , (unsigned int)g_p_mng_memory);)
   492     } else {
   493       _P(printf("[vpx][mm] Couldn't allocate memory:%d for vpx memory manager.\n"
   494 , g_mm_memory_size);)
   496       i_rv = -1;
   497     }
   499     if (g_p_mng_memory)
   500 #endif
   501     {
   502       int chunk_size = 0;
   504       g_mng_memory_allocated = 1;
   506       hmm_init(&hmm_d);
   508       chunk_size = g_mm_memory_size >> SHIFT_HMM_ADDR_ALIGN_UNIT;
   510       chunk_size -= DUMMY_END_BLOCK_BAUS;
   512       _P(printf("[vpx][mm] memory size:%d for vpx memory manager. g_p_mng_memory:0x%x  chunk_size:%d\n"
   513 , g_mm_memory_size
   514 , (unsigned int)g_p_mng_memory
   515 , chunk_size);)
   517       hmm_new_chunk(&hmm_d, (void *)g_p_mng_memory, chunk_size);
   518     }
   520 #if MM_DYNAMIC_MEMORY
   521     else {
   522       _P(printf("[vpx][mm] Couldn't allocate memory:%d for vpx memory manager.\n"
   523 , g_mm_memory_size);)
   525       i_rv = -1;
   526     }
   528 #endif
   529   }
   531   return i_rv;
   532 }
   534 static void *vpx_mm_realloc(void *memblk, size_t size) {
   535   void *p_ret = NULL;
   537   if (vpx_mm_create_heap_memory() < 0) {
   538     _P(printf("[vpx][mm] ERROR vpx_mm_realloc() Couldn't create memory for Heap.\n");)
   539   } else {
   540     int i_rv = 0;
   541     int old_num_aaus;
   542     int new_num_aaus;
   544     old_num_aaus = hmm_true_size(memblk);
   545     new_num_aaus = (size >> SHIFT_HMM_ADDR_ALIGN_UNIT) + 1;
   547     if (old_num_aaus == new_num_aaus) {
   548       p_ret = memblk;
   549     } else {
   550       i_rv = hmm_resize(&hmm_d, memblk, new_num_aaus);
   552       if (i_rv == 0) {
   553         p_ret = memblk;
   554       } else {
   555         /* Error. Try to malloc and then copy data. */
   556         void *p_from_malloc;
   558         new_num_aaus = (size >> SHIFT_HMM_ADDR_ALIGN_UNIT) + 1;
   559         p_from_malloc  = hmm_alloc(&hmm_d, new_num_aaus);
   561         if (p_from_malloc) {
   562           vpx_memcpy(p_from_malloc, memblk, size);
   563           hmm_free(&hmm_d, memblk);
   565           p_ret = p_from_malloc;
   566         }
   567       }
   568     }
   569   }
   571   return p_ret;
   572 }
   573 #endif /*CONFIG_MEM_MANAGER*/
   575 #if USE_GLOBAL_FUNCTION_POINTERS
   576 # if CONFIG_MEM_TRACKER
   577 extern int vpx_memory_tracker_set_functions(g_malloc_func g_malloc_l
   578 , g_calloc_func g_calloc_l
   579 , g_realloc_func g_realloc_l
   580 , g_free_func g_free_l
   581 , g_memcpy_func g_memcpy_l
   582 , g_memset_func g_memset_l
   583 , g_memmove_func g_memmove_l);
   584 # endif
   585 #endif /*USE_GLOBAL_FUNCTION_POINTERS*/
   586 int vpx_mem_set_functions(g_malloc_func g_malloc_l
   587 , g_calloc_func g_calloc_l
   588 , g_realloc_func g_realloc_l
   589 , g_free_func g_free_l
   590 , g_memcpy_func g_memcpy_l
   591 , g_memset_func g_memset_l
   592 , g_memmove_func g_memmove_l) {
   593 #if USE_GLOBAL_FUNCTION_POINTERS
   595   /* If use global functions is turned on then the
   596   application must set the global functions before
   597   it does anything else or vpx_mem will have
   598   unpredictable results. */
   599   if (!g_func) {
   600     g_func = (struct GLOBAL_FUNC_POINTERS *)
   601              g_malloc_l(sizeof(struct GLOBAL_FUNC_POINTERS));
   603     if (!g_func) {
   604       return -1;
   605     }
   606   }
   608 #if CONFIG_MEM_TRACKER
   609   {
   610     int rv = 0;
   611     rv = vpx_memory_tracker_set_functions(g_malloc_l
   612 , g_calloc_l
   613 , g_realloc_l
   614 , g_free_l
   615 , g_memcpy_l
   616 , g_memset_l
   617 , g_memmove_l);
   619     if (rv < 0) {
   620       return rv;
   621     }
   622   }
   623 #endif
   625   g_func->g_malloc  = g_malloc_l;
   626   g_func->g_calloc  = g_calloc_l;
   627   g_func->g_realloc = g_realloc_l;
   628   g_func->g_free    = g_free_l;
   629   g_func->g_memcpy  = g_memcpy_l;
   630   g_func->g_memset  = g_memset_l;
   631   g_func->g_memmove = g_memmove_l;
   633   return 0;
   634 #else
   635   (void)g_malloc_l;
   636   (void)g_calloc_l;
   637   (void)g_realloc_l;
   638   (void)g_free_l;
   639   (void)g_memcpy_l;
   640   (void)g_memset_l;
   641   (void)g_memmove_l;
   642   return -1;
   643 #endif
   644 }
   646 int vpx_mem_unset_functions() {
   647 #if USE_GLOBAL_FUNCTION_POINTERS
   649   if (g_func) {
   650     g_free_func temp_free = g_func->g_free;
   651     temp_free(g_func);
   652     g_func = NULL;
   653   }
   655 #endif
   656   return 0;
   657 }

mercurial