FramingIface_fuzz_test.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  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. struct Context
  23. {
  24. struct Iface internalIf;
  25. int currentMessage;
  26. // the expected output
  27. struct Message** messages;
  28. int messageCount;
  29. struct Allocator* alloc;
  30. Identity
  31. };
  32. static Iface_DEFUN messageOut(struct Message* msg, struct Iface* iface)
  33. {
  34. struct Context* ctx = Identity_check((struct Context*) iface);
  35. Assert_true(ctx->currentMessage < ctx->messageCount);
  36. // The list is populated backwards so we have to count down...
  37. struct Message* ctrlMsg = ctx->messages[ctx->messageCount - (++ctx->currentMessage)];
  38. Assert_true(ctrlMsg->length == msg->length);
  39. Assert_true(!Bits_memcmp(ctrlMsg->bytes, msg->bytes, msg->length));
  40. return 0;
  41. }
  42. /** The maximum size of a frame inside of one of the messages sent to the framing interface. */
  43. #define MAX_FRAME_SZ 2048
  44. /** The maximum size of a message which is sent to the frame interface. */
  45. #define MAX_MSG_SZ 2048
  46. /** Size of the buffer where we will be doing our work. */
  47. #define WORK_BUFF_SZ 4096
  48. #define CYCLES 100
  49. #define MIN_MSG_SZ 1
  50. #define MAX_MSGS_PER_FRAME 1024
  51. int main()
  52. {
  53. struct Allocator* mainAlloc = MallocAllocator_new(1<<20);
  54. struct Log* log = FileWriterLog_new(stdout, mainAlloc);
  55. struct Random* rand = Random_new(mainAlloc, log, NULL);
  56. struct Context* ctx = Allocator_calloc(mainAlloc, sizeof(struct Context), 1);
  57. Identity_set(ctx);
  58. ctx->internalIf.send = messageOut;
  59. struct Iface externalIf = { .send = NULL };
  60. struct Iface* fi = FramingIface_new(4096, &externalIf, mainAlloc);
  61. Iface_plumb(fi, &ctx->internalIf);
  62. for (int i = 0; i < CYCLES; i++) {
  63. struct Allocator* alloc = Allocator_child(mainAlloc);
  64. // max frame size must be at least 5 so that at least 1 byte of data is sent.
  65. int maxFrameSize = ( Random_uint32(rand) % (MAX_FRAME_SZ - 1) ) + 1;
  66. int minMessageSize = maxFrameSize / MAX_MSGS_PER_FRAME;
  67. if (minMessageSize < MIN_MSG_SZ) { minMessageSize = MIN_MSG_SZ; }
  68. int maxMessageSize = (Random_uint32(rand) % (MAX_MSG_SZ - minMessageSize)) + minMessageSize;
  69. if (maxMessageSize == minMessageSize) { maxMessageSize++; }
  70. // Log_debug(log, "maxFrameSize[%d] maxMessageSize[%d]", maxFrameSize, maxMessageSize);
  71. ctx->alloc = alloc;
  72. ctx->messages = NULL;
  73. ctx->messageCount = 0;
  74. ctx->currentMessage = 0;
  75. // Create one huge message, then create lots of little frames inside of it
  76. // then split it up in random places and send the sections to the framing
  77. // interface.
  78. struct Message* msg = Message_new(WORK_BUFF_SZ, 0, alloc);
  79. Assert_true(WORK_BUFF_SZ == msg->length);
  80. Random_bytes(rand, msg->bytes, msg->length);
  81. Message_shift(msg, -WORK_BUFF_SZ, NULL);
  82. for (;;) {
  83. int len = Random_uint32(rand) % maxFrameSize;
  84. if (!len) { len++; }
  85. if (msg->padding < len + 4) { break; }
  86. Message_shift(msg, len, NULL);
  87. ctx->messageCount++;
  88. ctx->messages =
  89. Allocator_realloc(alloc, ctx->messages, ctx->messageCount * sizeof(char*));
  90. struct Message* om = ctx->messages[ctx->messageCount-1] = Message_new(len, 0, alloc);
  91. Bits_memcpy(om->bytes, msg->bytes, len);
  92. Message_push32(msg, len, NULL);
  93. }
  94. do {
  95. int nextMessageSize =
  96. (Random_uint32(rand) % (maxMessageSize - minMessageSize)) + minMessageSize;
  97. if (!nextMessageSize) { nextMessageSize++; }
  98. if (nextMessageSize > msg->length) { nextMessageSize = msg->length; }
  99. struct Allocator* msgAlloc = Allocator_child(alloc);
  100. struct Message* m = Message_new(nextMessageSize, 0, msgAlloc);
  101. Message_pop(msg, m->bytes, nextMessageSize, NULL);
  102. Iface_send(&externalIf, m);
  103. Allocator_free(msgAlloc);
  104. } while (msg->length);
  105. Assert_true(ctx->messageCount == ctx->currentMessage);
  106. Allocator_free(alloc);
  107. }
  108. return 0;
  109. }