badCache.m 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. /*
  2. TEST_CRASHES
  3. TEST_RUN_OUTPUT
  4. arm
  5. OK: badCache.m
  6. OR
  7. crash now
  8. objc\[\d+\]: Method cache corrupted.*
  9. objc\[\d+\]: .*
  10. objc\[\d+\]: .*
  11. objc\[\d+\]: .*
  12. objc\[\d+\]: .*
  13. objc\[\d+\]: Method cache corrupted.*
  14. objc\[\d+\]: HALTED
  15. END
  16. */
  17. #include "test.h"
  18. // Test objc_msgSend's detection of infinite loops during cache scan.
  19. #if __arm__
  20. int main()
  21. {
  22. testwarn("objc_msgSend on arm doesn't detect infinite loops");
  23. fprintf(stderr, "arm\n");
  24. succeed(__FILE__);
  25. }
  26. #else
  27. #include "testroot.i"
  28. #if __LP64__
  29. typedef uint32_t mask_t;
  30. #else
  31. typedef uint16_t mask_t;
  32. #endif
  33. struct bucket_t {
  34. uintptr_t sel;
  35. uintptr_t imp;
  36. };
  37. struct cache_t {
  38. uintptr_t buckets;
  39. mask_t mask;
  40. mask_t occupied;
  41. };
  42. struct class_t {
  43. void *isa;
  44. void *supercls;
  45. struct cache_t cache;
  46. };
  47. @interface Subclass : TestRoot @end
  48. @implementation Subclass @end
  49. int main()
  50. {
  51. Class cls = [TestRoot class];
  52. id obj = [cls new];
  53. [obj self];
  54. struct cache_t *cache = &((__bridge struct class_t *)cls)->cache;
  55. // Figure out which cache mask scheme is in use by examining the existing bits.
  56. int low4 = 0;
  57. #if __LP64__
  58. int top16 = 0;
  59. #endif
  60. int outlined = 0;
  61. if (cache->buckets & 0xf) {
  62. low4 = 1;
  63. #if __LP64__
  64. } else if ((cache->buckets & (0xffffULL << 48))) {
  65. top16 = 1;
  66. #endif
  67. } else {
  68. outlined = 1;
  69. }
  70. # define COUNT 4
  71. # define COUNTSHIFT 14
  72. struct bucket_t *buckets = (struct bucket_t *)calloc(sizeof(struct bucket_t), COUNT+1);
  73. for (int i = 0; i < COUNT; i++) {
  74. buckets[i].sel = ~0;
  75. buckets[i].imp = ~0;
  76. }
  77. buckets[COUNT].sel = 1;
  78. buckets[COUNT].imp = (uintptr_t)buckets;
  79. if (low4) {
  80. cache->buckets = (uintptr_t)buckets | COUNTSHIFT;
  81. #if __LP64__
  82. } else if (top16) {
  83. cache->buckets = ((uintptr_t)(COUNT - 1) << 48) | (uintptr_t)buckets;
  84. #endif
  85. } else if (outlined) {
  86. cache->mask = COUNT-1;
  87. cache->buckets = (uintptr_t)buckets;
  88. }
  89. cache->occupied = 0;
  90. fprintf(stderr, "crash now\n");
  91. [obj self];
  92. fail("should have crashed");
  93. }
  94. #endif