dbmalloc.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. #include "dbmalloc.h"
  2. #include "dbutil.h"
  3. void * m_calloc(size_t nmemb, size_t size) {
  4. if (SIZE_T_MAX / nmemb < size) {
  5. dropbear_exit("m_calloc failed");
  6. }
  7. return m_malloc(nmemb*size);
  8. }
  9. void * m_strdup(const char * str) {
  10. char* ret;
  11. unsigned int len;
  12. len = strlen(str);
  13. ret = m_malloc(len+1);
  14. if (ret == NULL) {
  15. dropbear_exit("m_strdup failed");
  16. }
  17. memcpy(ret, str, len+1);
  18. return ret;
  19. }
  20. #if !DROPBEAR_TRACKING_MALLOC
  21. /* Simple wrappers around malloc etc */
  22. void * m_malloc(size_t size) {
  23. void* ret;
  24. if (size == 0) {
  25. dropbear_exit("m_malloc failed");
  26. }
  27. ret = calloc(1, size);
  28. if (ret == NULL) {
  29. dropbear_exit("m_malloc failed");
  30. }
  31. return ret;
  32. }
  33. void * m_realloc(void* ptr, size_t size) {
  34. void *ret;
  35. if (size == 0) {
  36. dropbear_exit("m_realloc failed");
  37. }
  38. ret = realloc(ptr, size);
  39. if (ret == NULL) {
  40. dropbear_exit("m_realloc failed");
  41. }
  42. return ret;
  43. }
  44. #else
  45. /* For fuzzing */
  46. struct dbmalloc_header {
  47. unsigned int epoch;
  48. struct dbmalloc_header *prev;
  49. struct dbmalloc_header *next;
  50. };
  51. static void put_alloc(struct dbmalloc_header *header);
  52. static void remove_alloc(struct dbmalloc_header *header);
  53. /* end of the linked list */
  54. static struct dbmalloc_header* staple;
  55. unsigned int current_epoch = 0;
  56. void m_malloc_set_epoch(unsigned int epoch) {
  57. current_epoch = epoch;
  58. }
  59. void m_malloc_free_epoch(unsigned int epoch, int dofree) {
  60. struct dbmalloc_header* header;
  61. struct dbmalloc_header* nextheader = NULL;
  62. struct dbmalloc_header* oldstaple = staple;
  63. staple = NULL;
  64. /* free allocations from this epoch, create a new staple-anchored list from
  65. the remainder */
  66. for (header = oldstaple; header; header = nextheader)
  67. {
  68. nextheader = header->next;
  69. if (header->epoch == epoch) {
  70. if (dofree) {
  71. free(header);
  72. }
  73. } else {
  74. header->prev = NULL;
  75. header->next = NULL;
  76. put_alloc(header);
  77. }
  78. }
  79. }
  80. static void put_alloc(struct dbmalloc_header *header) {
  81. assert(header->next == NULL);
  82. assert(header->prev == NULL);
  83. if (staple) {
  84. staple->prev = header;
  85. }
  86. header->next = staple;
  87. staple = header;
  88. }
  89. static void remove_alloc(struct dbmalloc_header *header) {
  90. if (header->prev) {
  91. header->prev->next = header->next;
  92. }
  93. if (header->next) {
  94. header->next->prev = header->prev;
  95. }
  96. if (staple == header) {
  97. staple = header->next;
  98. }
  99. header->prev = NULL;
  100. header->next = NULL;
  101. }
  102. static struct dbmalloc_header* get_header(void* ptr) {
  103. char* bptr = ptr;
  104. return (struct dbmalloc_header*)&bptr[-sizeof(struct dbmalloc_header)];
  105. }
  106. void * m_malloc(size_t size) {
  107. char* mem = NULL;
  108. struct dbmalloc_header* header = NULL;
  109. if (size == 0 || size > 1e9) {
  110. dropbear_exit("m_malloc failed");
  111. }
  112. size = size + sizeof(struct dbmalloc_header);
  113. mem = calloc(1, size);
  114. if (mem == NULL) {
  115. dropbear_exit("m_malloc failed");
  116. }
  117. header = (struct dbmalloc_header*)mem;
  118. put_alloc(header);
  119. header->epoch = current_epoch;
  120. return &mem[sizeof(struct dbmalloc_header)];
  121. }
  122. void * m_realloc(void* ptr, size_t size) {
  123. char* mem = NULL;
  124. struct dbmalloc_header* header = NULL;
  125. if (size == 0 || size > 1e9) {
  126. dropbear_exit("m_realloc failed");
  127. }
  128. header = get_header(ptr);
  129. remove_alloc(header);
  130. size = size + sizeof(struct dbmalloc_header);
  131. mem = realloc(header, size);
  132. if (mem == NULL) {
  133. dropbear_exit("m_realloc failed");
  134. }
  135. header = (struct dbmalloc_header*)mem;
  136. put_alloc(header);
  137. return &mem[sizeof(struct dbmalloc_header)];
  138. }
  139. void m_free_direct(void* ptr) {
  140. struct dbmalloc_header* header = NULL;
  141. if (!ptr) {
  142. return;
  143. }
  144. header = get_header(ptr);
  145. remove_alloc(header);
  146. free(header);
  147. }
  148. #endif /* DROPBEAR_TRACKING_MALLOC */
  149. void * m_realloc_ltm(void* ptr, size_t oldsize, size_t newsize) {
  150. (void)oldsize;
  151. return m_realloc(ptr, newsize);
  152. }
  153. void m_free_ltm(void *mem, size_t size) {
  154. (void)size;
  155. m_free_direct(mem);
  156. }