regression3.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Regression3
  4. * Description:
  5. * Helper radix_tree_iter_retry resets next_index to the current index.
  6. * In following radix_tree_next_slot current chunk size becomes zero.
  7. * This isn't checked and it tries to dereference null pointer in slot.
  8. *
  9. * Helper radix_tree_iter_resume reset slot to NULL and next_index to index + 1,
  10. * for tagger iteraction it also must reset cached tags in iterator to abort
  11. * next radix_tree_next_slot and go to slow-path into radix_tree_next_chunk.
  12. *
  13. * Running:
  14. * This test should run to completion immediately. The above bug would
  15. * cause it to segfault.
  16. *
  17. * Upstream commit:
  18. * Not yet
  19. */
  20. #include <linux/kernel.h>
  21. #include <linux/gfp.h>
  22. #include <linux/slab.h>
  23. #include <linux/radix-tree.h>
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26. #include "regression.h"
  27. void regression3_test(void)
  28. {
  29. RADIX_TREE(root, GFP_KERNEL);
  30. void *ptr0 = (void *)4ul;
  31. void *ptr = (void *)8ul;
  32. struct radix_tree_iter iter;
  33. void **slot;
  34. bool first;
  35. printv(1, "running regression test 3 (should take milliseconds)\n");
  36. radix_tree_insert(&root, 0, ptr0);
  37. radix_tree_tag_set(&root, 0, 0);
  38. first = true;
  39. radix_tree_for_each_tagged(slot, &root, &iter, 0, 0) {
  40. printv(2, "tagged %ld %p\n", iter.index, *slot);
  41. if (first) {
  42. radix_tree_insert(&root, 1, ptr);
  43. radix_tree_tag_set(&root, 1, 0);
  44. first = false;
  45. }
  46. if (radix_tree_deref_retry(*slot)) {
  47. printv(2, "retry at %ld\n", iter.index);
  48. slot = radix_tree_iter_retry(&iter);
  49. continue;
  50. }
  51. }
  52. radix_tree_delete(&root, 1);
  53. first = true;
  54. radix_tree_for_each_slot(slot, &root, &iter, 0) {
  55. printv(2, "slot %ld %p\n", iter.index, *slot);
  56. if (first) {
  57. radix_tree_insert(&root, 1, ptr);
  58. first = false;
  59. }
  60. if (radix_tree_deref_retry(*slot)) {
  61. printv(2, "retry at %ld\n", iter.index);
  62. slot = radix_tree_iter_retry(&iter);
  63. continue;
  64. }
  65. }
  66. radix_tree_delete(&root, 1);
  67. first = true;
  68. radix_tree_for_each_contig(slot, &root, &iter, 0) {
  69. printv(2, "contig %ld %p\n", iter.index, *slot);
  70. if (first) {
  71. radix_tree_insert(&root, 1, ptr);
  72. first = false;
  73. }
  74. if (radix_tree_deref_retry(*slot)) {
  75. printv(2, "retry at %ld\n", iter.index);
  76. slot = radix_tree_iter_retry(&iter);
  77. continue;
  78. }
  79. }
  80. radix_tree_for_each_slot(slot, &root, &iter, 0) {
  81. printv(2, "slot %ld %p\n", iter.index, *slot);
  82. if (!iter.index) {
  83. printv(2, "next at %ld\n", iter.index);
  84. slot = radix_tree_iter_resume(slot, &iter);
  85. }
  86. }
  87. radix_tree_for_each_contig(slot, &root, &iter, 0) {
  88. printv(2, "contig %ld %p\n", iter.index, *slot);
  89. if (!iter.index) {
  90. printv(2, "next at %ld\n", iter.index);
  91. slot = radix_tree_iter_resume(slot, &iter);
  92. }
  93. }
  94. radix_tree_tag_set(&root, 0, 0);
  95. radix_tree_tag_set(&root, 1, 0);
  96. radix_tree_for_each_tagged(slot, &root, &iter, 0, 0) {
  97. printv(2, "tagged %ld %p\n", iter.index, *slot);
  98. if (!iter.index) {
  99. printv(2, "next at %ld\n", iter.index);
  100. slot = radix_tree_iter_resume(slot, &iter);
  101. }
  102. }
  103. radix_tree_delete(&root, 0);
  104. radix_tree_delete(&root, 1);
  105. printv(1, "regression test 3 passed\n");
  106. }