memory.c 3.7 KB

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