test_sshbuf_fuzz.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /* $OpenBSD: test_sshbuf_fuzz.c,v 1.2 2018/10/17 23:28:05 djm Exp $ */
  2. /*
  3. * Regress test for sshbuf.h buffer API
  4. *
  5. * Placed in the public domain
  6. */
  7. #include "includes.h"
  8. #include <sys/types.h>
  9. #include <sys/param.h>
  10. #include <stdio.h>
  11. #ifdef HAVE_STDINT_H
  12. # include <stdint.h>
  13. #endif
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include "../test_helper/test_helper.h"
  17. #include "ssherr.h"
  18. #include "sshbuf.h"
  19. #define NUM_FUZZ_TESTS (1 << 18)
  20. void sshbuf_fuzz_tests(void);
  21. void
  22. sshbuf_fuzz_tests(void)
  23. {
  24. struct sshbuf *p1;
  25. u_char *dp;
  26. size_t sz, sz2, i, ntests = NUM_FUZZ_TESTS;
  27. u_int32_t r;
  28. int ret;
  29. if (test_is_fast())
  30. ntests >>= 2;
  31. if (test_is_slow())
  32. ntests <<= 2;
  33. /* NB. uses sshbuf internals */
  34. TEST_START("fuzz alloc/dealloc");
  35. p1 = sshbuf_new();
  36. ASSERT_INT_EQ(sshbuf_set_max_size(p1, 16 * 1024), 0);
  37. ASSERT_PTR_NE(p1, NULL);
  38. ASSERT_PTR_NE(sshbuf_ptr(p1), NULL);
  39. ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1));
  40. for (i = 0; i < NUM_FUZZ_TESTS; i++) {
  41. r = arc4random_uniform(10);
  42. if (r == 0) {
  43. /* 10% chance: small reserve */
  44. r = arc4random_uniform(10);
  45. fuzz_reserve:
  46. sz = sshbuf_avail(p1);
  47. sz2 = sshbuf_len(p1);
  48. ret = sshbuf_reserve(p1, r, &dp);
  49. if (ret < 0) {
  50. ASSERT_PTR_EQ(dp, NULL);
  51. ASSERT_SIZE_T_LT(sz, r);
  52. ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz);
  53. ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2);
  54. } else {
  55. ASSERT_PTR_NE(dp, NULL);
  56. ASSERT_SIZE_T_GE(sz, r);
  57. ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz - r);
  58. ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2 + r);
  59. memset(dp, arc4random_uniform(255) + 1, r);
  60. }
  61. } else if (r < 3) {
  62. /* 20% chance: big reserve */
  63. r = arc4random_uniform(8 * 1024);
  64. goto fuzz_reserve;
  65. } else if (r == 3) {
  66. /* 10% chance: small consume */
  67. r = arc4random_uniform(10);
  68. fuzz_consume:
  69. sz = sshbuf_avail(p1);
  70. sz2 = sshbuf_len(p1);
  71. /* 50% change consume from end, otherwise start */
  72. ret = ((arc4random() & 1) ?
  73. sshbuf_consume : sshbuf_consume_end)(p1, r);
  74. if (ret < 0) {
  75. ASSERT_SIZE_T_LT(sz2, r);
  76. ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz);
  77. ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2);
  78. } else {
  79. ASSERT_SIZE_T_GE(sz2, r);
  80. ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz + r);
  81. ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2 - r);
  82. }
  83. } else if (r < 8) {
  84. /* 40% chance: big consume */
  85. r = arc4random_uniform(2 * 1024);
  86. goto fuzz_consume;
  87. } else if (r == 8) {
  88. /* 10% chance: reset max size */
  89. r = arc4random_uniform(16 * 1024);
  90. sz = sshbuf_max_size(p1);
  91. if (sshbuf_set_max_size(p1, r) < 0)
  92. ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), sz);
  93. else
  94. ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), r);
  95. } else {
  96. if (arc4random_uniform(8192) == 0) {
  97. /* tiny chance: new buffer */
  98. ASSERT_PTR_NE(sshbuf_ptr(p1), NULL);
  99. ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1));
  100. sshbuf_free(p1);
  101. p1 = sshbuf_new();
  102. ASSERT_PTR_NE(p1, NULL);
  103. ASSERT_INT_EQ(sshbuf_set_max_size(p1,
  104. 16 * 1024), 0);
  105. } else {
  106. /* Almost 10%: giant reserve */
  107. /* use arc4random_buf for r > 2^32 on 64 bit */
  108. arc4random_buf(&r, sizeof(r));
  109. while (r < SSHBUF_SIZE_MAX / 2) {
  110. r <<= 1;
  111. r |= arc4random() & 1;
  112. }
  113. goto fuzz_reserve;
  114. }
  115. }
  116. ASSERT_PTR_NE(sshbuf_ptr(p1), NULL);
  117. ASSERT_SIZE_T_LE(sshbuf_max_size(p1), 16 * 1024);
  118. }
  119. ASSERT_PTR_NE(sshbuf_ptr(p1), NULL);
  120. ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1));
  121. sshbuf_free(p1);
  122. TEST_DONE();
  123. }