FramingInterface_fuzz_test.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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 "crypto/random/Random.h"
  16. #include "interface/Interface.h"
  17. #include "interface/FramingInterface.h"
  18. #include "memory/Allocator.h"
  19. #include "memory/MallocAllocator.h"
  20. #include "util/Bits.h"
  21. #include "util/Identity.h"
  22. #include "util/log/FileWriterLog.h"
  23. struct Context
  24. {
  25. int currentMessage;
  26. // the expected output
  27. struct Message** messages;
  28. int messageCount;
  29. struct Allocator* alloc;
  30. Identity
  31. };
  32. static uint8_t messageOut(struct Message* msg, struct Interface* iface)
  33. {
  34. struct Context* ctx = Identity_check((struct Context*) iface->receiverContext);
  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. /**
  50. * This is just to keep the test from running for a silly-long-time because of choosing a
  51. * number like 1, after changes to the code, it's advisible to set this to 1 and run the
  52. * test for a while to see if anything has been broken.
  53. */
  54. #define MIN_MSG_SZ 1
  55. int main()
  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_malloc(mainAlloc, sizeof(struct Context));
  61. Identity_set(ctx);
  62. struct Interface iface = { .sendMessage = NULL };
  63. struct Interface* fi = FramingInterface_new(4096, &iface, mainAlloc);
  64. fi->receiveMessage = messageOut;
  65. fi->receiverContext = ctx;
  66. for (int i = 0; i < CYCLES; i++) {
  67. struct Allocator* alloc = Allocator_child(mainAlloc);
  68. // max frame size must be at least 5 so that at least 1 byte of data is sent.
  69. int maxFrameSize = ( Random_uint32(rand) % (MAX_FRAME_SZ - 1) ) + 1;
  70. int maxMessageSize = ( Random_uint32(rand) % (MAX_MSG_SZ - MIN_MSG_SZ) ) + MIN_MSG_SZ;
  71. Log_debug(log, "maxFrameSize[%d] maxMessageSize[%d]", maxFrameSize, maxMessageSize);
  72. ctx->alloc = alloc;
  73. ctx->messages = NULL;
  74. ctx->messageCount = 0;
  75. ctx->currentMessage = 0;
  76. // Create one huge message, then create lots of little frames inside of it
  77. // then split it up in random places and send the sections to the framing
  78. // interface.
  79. struct Message* msg = Message_new(WORK_BUFF_SZ, 0, alloc);
  80. Assert_true(WORK_BUFF_SZ == msg->length);
  81. Random_bytes(rand, msg->bytes, msg->length);
  82. Message_shift(msg, -WORK_BUFF_SZ, NULL);
  83. for (;;) {
  84. int len = Random_uint32(rand) % maxFrameSize;
  85. if (!len) { len++; }
  86. if (msg->padding < len + 4) { break; }
  87. Message_shift(msg, len, NULL);
  88. ctx->messageCount++;
  89. ctx->messages =
  90. Allocator_realloc(alloc, ctx->messages, ctx->messageCount * sizeof(char*));
  91. struct Message* om = ctx->messages[ctx->messageCount-1] = Message_new(len, 0, alloc);
  92. Bits_memcpy(om->bytes, msg->bytes, len);
  93. Message_push32(msg, len, NULL);
  94. }
  95. do {
  96. int nextMessageSize = Random_uint32(rand) % maxMessageSize;
  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. Interface_receiveMessage(&iface, 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. }