FramingIface_fuzz_test.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #include "interface/FramingIface.h"
  16. #include "crypto/random/Random.h"
  17. #include "memory/Allocator.h"
  18. #include "memory/MallocAllocator.h"
  19. #include "util/Bits.h"
  20. #include "util/Identity.h"
  21. #include "util/log/FileWriterLog.h"
  22. #include "util/CString.h"
  23. #include "crypto/random/test/DeterminentRandomSeed.h"
  24. struct Context
  25. {
  26. struct Iface internalIf;
  27. int currentMessage;
  28. // the expected output
  29. struct Message** messages;
  30. int messageCount;
  31. struct Allocator* alloc;
  32. Identity
  33. };
  34. static Iface_DEFUN messageOut(struct Message* msg, struct Iface* iface)
  35. {
  36. struct Context* ctx = Identity_check((struct Context*) iface);
  37. Assert_true(ctx->currentMessage < ctx->messageCount);
  38. // The list is populated backwards so we have to count down...
  39. struct Message* ctrlMsg = ctx->messages[ctx->messageCount - (++ctx->currentMessage)];
  40. Assert_true(ctrlMsg->length == msg->length);
  41. Assert_true(!Bits_memcmp(ctrlMsg->bytes, msg->bytes, msg->length));
  42. return 0;
  43. }
  44. /** The maximum size of a frame inside of one of the messages sent to the framing interface. */
  45. #define MAX_FRAME_SZ 2048
  46. /** The maximum size of a message which is sent to the frame interface. */
  47. #define MAX_MSG_SZ 2048
  48. /** Size of the buffer where we will be doing our work. */
  49. #define WORK_BUFF_SZ 4096
  50. #define QUICK_CYCLES 100
  51. #define SLOW_CYCLES 200000
  52. #define CYCLES 100
  53. #define MIN_MSG_SZ 1
  54. #define MAX_MSGS_PER_FRAME 1024
  55. int main(int argc, char** argv)
  56. {
  57. struct Allocator* mainAlloc = MallocAllocator_new(1<<20);
  58. struct Log* log = FileWriterLog_new(stdout, mainAlloc);
  59. struct Random* rand = Random_new(mainAlloc, log, NULL);
  60. struct Context* ctx = Allocator_calloc(mainAlloc, sizeof(struct Context), 1);
  61. Identity_set(ctx);
  62. ctx->internalIf.send = messageOut;
  63. struct Iface externalIf = { .send = NULL };
  64. struct Iface* fi = FramingIface_new(4096, &externalIf, mainAlloc);
  65. Iface_plumb(fi, &ctx->internalIf);
  66. int cycles = QUICK_CYCLES;
  67. for (int i = 0; i < argc; i++) {
  68. if (!CString_strcmp("--fuzz", argv[i])) {
  69. cycles = SLOW_CYCLES;
  70. break;
  71. }
  72. }
  73. for (int i = 0; i < cycles; i++) {
  74. struct Allocator* alloc = Allocator_child(mainAlloc);
  75. // max frame size must be at least 5 so that at least 1 byte of data is sent.
  76. int maxFrameSize = ( Random_uint32(rand) % (MAX_FRAME_SZ - 1) ) + 1;
  77. int minMessageSize = maxFrameSize / MAX_MSGS_PER_FRAME;
  78. if (minMessageSize < MIN_MSG_SZ) { minMessageSize = MIN_MSG_SZ; }
  79. int maxMessageSize = (Random_uint32(rand) % (MAX_MSG_SZ - minMessageSize)) + minMessageSize;
  80. if (maxMessageSize == minMessageSize) { maxMessageSize++; }
  81. // Log_debug(log, "maxFrameSize[%d] maxMessageSize[%d]", maxFrameSize, maxMessageSize);
  82. ctx->alloc = alloc;
  83. ctx->messages = NULL;
  84. ctx->messageCount = 0;
  85. ctx->currentMessage = 0;
  86. // Create one huge message, then create lots of little frames inside of it
  87. // then split it up in random places and send the sections to the framing
  88. // interface.
  89. struct Message* msg = Message_new(WORK_BUFF_SZ, 0, alloc);
  90. Assert_true(WORK_BUFF_SZ == msg->length);
  91. Random_bytes(rand, msg->bytes, msg->length);
  92. Message_shift(msg, -WORK_BUFF_SZ, NULL);
  93. for (;;) {
  94. int len = Random_uint32(rand) % maxFrameSize;
  95. if (!len) { len++; }
  96. if (msg->padding < len + 4) { break; }
  97. Message_shift(msg, len, NULL);
  98. ctx->messageCount++;
  99. ctx->messages =
  100. Allocator_realloc(alloc, ctx->messages, ctx->messageCount * sizeof(char*));
  101. struct Message* om = ctx->messages[ctx->messageCount-1] = Message_new(len, 0, alloc);
  102. Bits_memcpy(om->bytes, msg->bytes, len);
  103. Message_push32(msg, len, NULL);
  104. }
  105. int i = 0;
  106. do {
  107. int nextMessageSize =
  108. (Random_uint32(rand) % (maxMessageSize - minMessageSize)) + minMessageSize;
  109. // Prevent oom conditions.
  110. if (i++ > 1000) { nextMessageSize = msg->length; }
  111. if (!nextMessageSize) { nextMessageSize++; }
  112. if (nextMessageSize > msg->length) { nextMessageSize = msg->length; }
  113. struct Allocator* msgAlloc = Allocator_child(alloc);
  114. struct Message* m = Message_new(nextMessageSize, 0, msgAlloc);
  115. Message_pop(msg, m->bytes, nextMessageSize, NULL);
  116. Iface_send(&externalIf, m);
  117. Allocator_free(msgAlloc);
  118. } while (msg->length);
  119. Assert_true(ctx->messageCount == ctx->currentMessage);
  120. Allocator_free(alloc);
  121. }
  122. Log_debug(log, "===+++=== Completed Ok ===++++===");
  123. Allocator_free(mainAlloc);
  124. return 0;
  125. }