memory.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /*
  2. * PuTTY's memory allocation wrappers.
  3. */
  4. #ifdef ALLOCATION_ALIGNMENT
  5. /* Before we include standard headers, define _ISOC11_SOURCE so that
  6. * we get the declaration of aligned_alloc(). */
  7. #define _ISOC11_SOURCE
  8. #endif
  9. #include <assert.h>
  10. #include <stdlib.h>
  11. #include <limits.h>
  12. #include "defs.h"
  13. #include "puttymem.h"
  14. #include "misc.h"
  15. void *safemalloc(size_t factor1, size_t factor2, size_t addend)
  16. {
  17. if (factor1 > SIZE_MAX / factor2)
  18. goto fail;
  19. size_t product = factor1 * factor2;
  20. if (addend > SIZE_MAX)
  21. goto fail;
  22. if (product > SIZE_MAX - addend)
  23. goto fail;
  24. size_t size = product + addend;
  25. if (size == 0)
  26. size = 1;
  27. void *p;
  28. #ifdef MINEFIELD
  29. p = minefield_c_malloc(size);
  30. #elif defined ALLOCATION_ALIGNMENT
  31. /* aligned_alloc requires the allocation size to be rounded up */
  32. p = aligned_alloc(
  33. ALLOCATION_ALIGNMENT,
  34. (size + ALLOCATION_ALIGNMENT - 1) & ~(ALLOCATION_ALIGNMENT-1));
  35. #else
  36. p = malloc(size);
  37. #endif
  38. if (!p)
  39. goto fail;
  40. return p;
  41. fail:
  42. out_of_memory();
  43. }
  44. void *saferealloc(void *ptr, size_t n, size_t size)
  45. {
  46. void *p;
  47. if (n > INT_MAX / size) {
  48. p = NULL;
  49. } else {
  50. size *= n;
  51. if (!ptr) {
  52. #ifdef MINEFIELD
  53. p = minefield_c_malloc(size);
  54. #elif defined ALLOCATION_ALIGNMENT
  55. p = aligned_alloc(ALLOCATION_ALIGNMENT, size);
  56. #else
  57. p = malloc(size);
  58. #endif
  59. } else {
  60. #ifdef MINEFIELD
  61. p = minefield_c_realloc(ptr, size);
  62. #else
  63. p = realloc(ptr, size);
  64. #endif
  65. }
  66. }
  67. if (!p)
  68. out_of_memory();
  69. return p;
  70. }
  71. void safefree(void *ptr)
  72. {
  73. if (ptr) {
  74. #ifdef MINEFIELD
  75. minefield_c_free(ptr);
  76. #else
  77. free(ptr);
  78. #endif
  79. }
  80. }
  81. void *safegrowarray(void *ptr, size_t *allocated, size_t eltsize,
  82. size_t oldlen, size_t extralen, bool secret)
  83. {
  84. /* The largest value we can safely multiply by eltsize */
  85. assert(eltsize > 0);
  86. size_t maxsize = (~(size_t)0) / eltsize;
  87. size_t oldsize = *allocated;
  88. /* Range-check the input values */
  89. assert(oldsize <= maxsize);
  90. assert(oldlen <= maxsize);
  91. assert(extralen <= maxsize - oldlen);
  92. /* If the size is already enough, don't bother doing anything! */
  93. if (oldsize > oldlen + extralen)
  94. return ptr;
  95. /* Find out how much we need to grow the array by. */
  96. size_t increment = (oldlen + extralen) - oldsize;
  97. /* Invent a new size. We want to grow the array by at least
  98. * 'increment' elements; by at least a fixed number of bytes (to
  99. * get things started when sizes are small); and by some constant
  100. * factor of its old size (to avoid repeated calls to this
  101. * function taking quadratic time overall). */
  102. if (increment < 256 / eltsize)
  103. increment = 256 / eltsize;
  104. if (increment < oldsize / 16)
  105. increment = oldsize / 16;
  106. /* But we also can't grow beyond maxsize. */
  107. size_t maxincr = maxsize - oldsize;
  108. if (increment > maxincr)
  109. increment = maxincr;
  110. size_t newsize = oldsize + increment;
  111. void *toret;
  112. if (secret) {
  113. toret = safemalloc(newsize, eltsize, 0);
  114. if (oldsize) {
  115. memcpy(toret, ptr, oldsize * eltsize);
  116. smemclr(ptr, oldsize * eltsize);
  117. sfree(ptr);
  118. }
  119. } else {
  120. toret = saferealloc(ptr, newsize, eltsize);
  121. }
  122. *allocated = newsize;
  123. return toret;
  124. }