aboutsummaryrefslogblamecommitdiff
path: root/include/alloc-inl.h
blob: 5764e30b23f7e344c8feface9c8f9e601d9590a2 (plain) (tree)
1
2
3
4
5
6
7
8
9
  

                                                                       
 
                                        
 
                                               

                                                                      
 
                                                        
                                                                

























                                                                               




                                                      
                                                      



                                                      




                                                                      




                                                                       



                                                    




                                                                       

             

                                                  
                         
 




                                                                            
          



                         
                     

                                
                    


 












                                                 
                  


                                           
            


 





                                                                                

                   







                      

                         
                            

                                
                                                                  
 
                    


 




                                                                       
                                  
 



                                    



                                                                            

           





                                
                     

                                



                                




                                                                             
          



                                 
                     
                                
 



                                









                                                                               
                         
                                
 






                         


                                                                                







                                             
 
                      
 
                                                                              
 
/*
   american fuzzy lop++ - error-checking, memory-zeroing alloc routines
   --------------------------------------------------------------------

   Originally written by Michal Zalewski

   Now maintained by Marc Heuse <mh@mh-sec.de>,
                        Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
                        Andrea Fioraldi <andreafioraldi@gmail.com>

   Copyright 2016, 2017 Google Inc. All rights reserved.
   Copyright 2019-2020 AFLplusplus Project. All rights reserved.

   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

   This allocator is not designed to resist malicious attackers (the canaries
   are small and predictable), but provides a robust and portable way to detect
   use-after-free, off-by-one writes, stale pointers, and so on.

 */

#ifndef _HAVE_ALLOC_INL_H
#define _HAVE_ALLOC_INL_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "config.h"
#include "types.h"
#include "debug.h"

/* User-facing macro to sprintf() to a dynamically allocated buffer. */

#define alloc_printf(_str...)                        \
  ({                                                 \
                                                     \
    u8* _tmp;                                        \
    s32 _len = snprintf(NULL, 0, _str);              \
    if (_len < 0) FATAL("Whoa, snprintf() fails?!"); \
    _tmp = ck_alloc(_len + 1);                       \
    snprintf((char*)_tmp, _len + 1, _str);           \
    _tmp;                                            \
                                                     \
  })

/* Macro to enforce allocation limits as a last-resort defense against
   integer overflows. */

#define ALLOC_CHECK_SIZE(_s)                                          \
  do {                                                                \
                                                                      \
    if ((_s) > MAX_ALLOC) ABORT("Bad alloc request: %u bytes", (_s)); \
                                                                      \
  } while (0)

/* Macro to check malloc() failures and the like. */

#define ALLOC_CHECK_RESULT(_r, _s)                                    \
  do {                                                                \
                                                                      \
    if (!(_r)) ABORT("Out of memory: can't allocate %u bytes", (_s)); \
                                                                      \
  } while (0)

/* Allocator increments for ck_realloc_block(). */

#define ALLOC_BLK_INC 256

/* Allocate a buffer, explicitly not zeroing it. Returns NULL for zero-sized
   requests. */

static inline void* DFL_ck_alloc_nozero(u32 size) {

  u8* ret;

  if (!size) return NULL;

  ALLOC_CHECK_SIZE(size);
  ret = malloc(size);
  ALLOC_CHECK_RESULT(ret, size);

  return (void*)ret;

}

/* Allocate a buffer, returning zeroed memory. */

static inline void* DFL_ck_alloc(u32 size) {

  void* mem;

  if (!size) return NULL;
  mem = DFL_ck_alloc_nozero(size);

  return memset(mem, 0, size);

}

/* Free memory  */

static inline void DFL_ck_free(void* mem) {

  free(mem);

}

/* Re-allocate a buffer, checking for issues and zeroing any newly-added tail.
   With DEBUG_BUILD, the buffer is always reallocated to a new addresses and the
   old memory is clobbered with 0xFF. */

static inline void* DFL_ck_realloc(void* orig, u32 size) {

  u8* ret;
  u32 old_size = 0;

  if (!size) {

    DFL_ck_free(orig);
    return NULL;

  }

  ALLOC_CHECK_SIZE(size);

  ret = realloc(orig, size);
  ALLOC_CHECK_RESULT(ret, size);

  if (size > old_size) memset(ret + old_size, 0, size - old_size);

  return (void*)ret;

}

/* Re-allocate a buffer with ALLOC_BLK_INC increments (used to speed up
   repeated small reallocs without complicating the user code). */

static inline void* DFL_ck_realloc_block(void* orig, u32 size) {

  if (orig) size += ALLOC_BLK_INC;

  return DFL_ck_realloc(orig, size);

}

/* Create a buffer with a copy of a string. Returns NULL for NULL inputs. */

static inline u8* DFL_ck_strdup(u8* str) {

  u8* ret;
  u32 size;

  if (!str) return NULL;

  size = strlen((char*)str) + 1;

  ALLOC_CHECK_SIZE(size);
  ret = malloc(size);
  ALLOC_CHECK_RESULT(ret, size);

  return memcpy(ret, str, size);

}

/* Create a buffer with a copy of a memory block. Returns NULL for zero-sized
   or NULL inputs. */

static inline void* DFL_ck_memdup(void* mem, u32 size) {

  u8* ret;

  if (!mem || !size) return NULL;

  ALLOC_CHECK_SIZE(size);
  ret = malloc(size);
  ALLOC_CHECK_RESULT(ret, size);

  return memcpy(ret, mem, size);

}

/* Create a buffer with a block of text, appending a NUL terminator at the end.
   Returns NULL for zero-sized or NULL inputs. */

static inline u8* DFL_ck_memdup_str(u8* mem, u32 size) {

  u8* ret;

  if (!mem || !size) return NULL;

  ALLOC_CHECK_SIZE(size);
  ret = malloc(size + 1);
  ALLOC_CHECK_RESULT(ret, size);

  memcpy(ret, mem, size);
  ret[size] = 0;

  return ret;

}

/* In non-debug mode, we just do straightforward aliasing of the above functions
   to user-visible names such as ck_alloc(). */

#define ck_alloc DFL_ck_alloc
#define ck_alloc_nozero DFL_ck_alloc_nozero
#define ck_realloc DFL_ck_realloc
#define ck_realloc_block DFL_ck_realloc_block
#define ck_strdup DFL_ck_strdup
#define ck_memdup DFL_ck_memdup
#define ck_memdup_str DFL_ck_memdup_str
#define ck_free DFL_ck_free

#define alloc_report()

#endif                                               /* ! _HAVE_ALLOC_INL_H */