tst-free-errno.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /* Test that free preserves errno.
  2. Copyright (C) 2020-2026 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <https://www.gnu.org/licenses/>. */
  15. #include <errno.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <unistd.h>
  19. #include <fcntl.h>
  20. #include <stdint.h>
  21. #include <string.h>
  22. #include <stdio.h>
  23. #include <sys/mman.h>
  24. #include <support/check.h>
  25. #include <support/support.h>
  26. #include <support/temp_file.h>
  27. /* The __attribute__ ((weak)) prevents a GCC optimization. Without
  28. it, GCC would "know" that errno is unchanged by calling free (ptr),
  29. when ptr was the result of a malloc call in the same function. */
  30. int __attribute__ ((weak))
  31. get_errno (void)
  32. {
  33. return errno;
  34. }
  35. static int
  36. do_test (void)
  37. {
  38. /* Check that free() preserves errno. */
  39. {
  40. errno = 1789; /* Liberté, égalité, fraternité. */
  41. free (NULL);
  42. TEST_VERIFY (get_errno () == 1789);
  43. }
  44. { /* Large memory allocations, to force mmap. */
  45. enum { N = 2 };
  46. void * volatile ptrs[N];
  47. size_t i;
  48. for (i = 0; i < N; i++)
  49. ptrs[i] = xmalloc (5318153);
  50. for (i = 0; i < N; i++)
  51. {
  52. errno = 1789;
  53. free (ptrs[i]);
  54. TEST_VERIFY (get_errno () == 1789);
  55. }
  56. }
  57. /* Test a less common code path.
  58. When malloc() is based on mmap(), free() can sometimes call munmap().
  59. munmap() usually succeeds, but fails in a particular situation: when
  60. - it has to unmap the middle part of a VMA, and
  61. - the number of VMAs of a process is limited and the limit is
  62. already reached.
  63. On Linux, the default VMA count limit is 65536 although many systems
  64. might override this. For this test, irrespective of the system, we
  65. try to create up to 65536 mappings in order to attempt to hit the
  66. limit. */
  67. {
  68. /* We expect the kernel to coalesce the VMAs for these large mallocs
  69. (which will be mmap'd by malloc due to their size). */
  70. size_t big_size = 0x3000000;
  71. void * volatile block1 = xmalloc (big_size - 100);
  72. void * volatile block2 = xmalloc (big_size - 100);
  73. void * volatile block3 = xmalloc (big_size - 100);
  74. /* If block2 lands between block1 and block3, we can continue the test
  75. since it depends on being able to free block2 to cause an munmap
  76. failure. */
  77. if (((block2 > block1) && (block2 > block3))
  78. || ((block2 < block1) && (block2 < block3)))
  79. printf
  80. ("warning: block2 was not allocated between block1 and block3\n");
  81. /* We will map this fd repeatedly to consume VMA mappings. */
  82. int fd = create_temp_file ("tst-free-errno", NULL);
  83. if (fd < 0)
  84. FAIL_EXIT1 ("cannot create temporary file for mmap'ing");
  85. /* Now add as many mappings as we can.
  86. Stop at 65536, in order not to crash the machine (in case the
  87. limit has been increased by the system administrator). */
  88. size_t pagesize = getpagesize ();
  89. for (int i = 0; i < 65536; i++)
  90. if (mmap (NULL, pagesize, PROT_READ, MAP_FILE | MAP_PRIVATE,
  91. fd, 0)
  92. == MAP_FAILED)
  93. break;
  94. /* Now the number of VMAs of this process has hopefully attained
  95. its limit. */
  96. errno = 1789;
  97. /* This call to free() is supposed to call munmap, which should
  98. fail because the fragmentation of a bigger coalesced VMA will
  99. lead to an increase in the number of VMAs which we already
  100. maxed out. */
  101. free (block2);
  102. TEST_VERIFY (get_errno () == 1789);
  103. }
  104. return 0;
  105. }
  106. #include <support/test-driver.c>