memory.c 2.7 KB

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