memory.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  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. p = aligned_alloc(ALLOCATION_ALIGNMENT, size);
  32. #else
  33. p = malloc(size);
  34. #endif
  35. if (!p)
  36. goto fail;
  37. return p;
  38. fail:
  39. out_of_memory();
  40. }
  41. void *saferealloc(void *ptr, size_t n, size_t size)
  42. {
  43. void *p;
  44. if (n > INT_MAX / size) {
  45. p = NULL;
  46. } else {
  47. size *= n;
  48. if (!ptr) {
  49. #ifdef MINEFIELD
  50. p = minefield_c_malloc(size);
  51. #elif defined ALLOCATION_ALIGNMENT
  52. p = aligned_alloc(ALLOCATION_ALIGNMENT, size);
  53. #else
  54. p = malloc(size);
  55. #endif
  56. } else {
  57. #ifdef MINEFIELD
  58. p = minefield_c_realloc(ptr, size);
  59. #else
  60. p = realloc(ptr, size);
  61. #endif
  62. }
  63. }
  64. if (!p)
  65. out_of_memory();
  66. return p;
  67. }
  68. void safefree(void *ptr)
  69. {
  70. if (ptr) {
  71. #ifdef MINEFIELD
  72. minefield_c_free(ptr);
  73. #else
  74. free(ptr);
  75. #endif
  76. }
  77. }
  78. void *safegrowarray(void *ptr, size_t *allocated, size_t eltsize,
  79. size_t oldlen, size_t extralen, bool secret)
  80. {
  81. /* The largest value we can safely multiply by eltsize */
  82. assert(eltsize > 0);
  83. size_t maxsize = (~(size_t)0) / eltsize;
  84. size_t oldsize = *allocated;
  85. /* Range-check the input values */
  86. assert(oldsize <= maxsize);
  87. assert(oldlen <= maxsize);
  88. assert(extralen <= maxsize - oldlen);
  89. /* If the size is already enough, don't bother doing anything! */
  90. if (oldsize > oldlen + extralen)
  91. return ptr;
  92. /* Find out how much we need to grow the array by. */
  93. size_t increment = (oldlen + extralen) - oldsize;
  94. /* Invent a new size. We want to grow the array by at least
  95. * 'increment' elements; by at least a fixed number of bytes (to
  96. * get things started when sizes are small); and by some constant
  97. * factor of its old size (to avoid repeated calls to this
  98. * function taking quadratic time overall). */
  99. if (increment < 256 / eltsize)
  100. increment = 256 / eltsize;
  101. if (increment < oldsize / 16)
  102. increment = oldsize / 16;
  103. /* But we also can't grow beyond maxsize. */
  104. size_t maxincr = maxsize - oldsize;
  105. if (increment > maxincr)
  106. increment = maxincr;
  107. size_t newsize = oldsize + increment;
  108. void *toret;
  109. if (secret) {
  110. toret = safemalloc(newsize, eltsize, 0);
  111. if (oldsize) {
  112. memcpy(toret, ptr, oldsize * eltsize);
  113. smemclr(ptr, oldsize * eltsize);
  114. sfree(ptr);
  115. }
  116. } else {
  117. toret = saferealloc(ptr, newsize, eltsize);
  118. }
  119. *allocated = newsize;
  120. return toret;
  121. }