1
0

memory.c 3.6 KB

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