lex.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. // SPDX-License-Identifier: GPL-2.0 or GPL-3.0
  2. // Copyright © 2018-2019 Ariadne Devos
  3. /* sHT -- test the lexer for Kleene closures of letter sets */
  4. /** Testing fragmentation in the lexer
  5. The HTTP header name can theoretically be fragmented, but typically,
  6. it isn't. Test fragmentation specially. TODO: test too long lexemes,
  7. unless it's common in some situation in s2. */
  8. #include <stddef.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <sHT/index.h>
  13. #include <sHT/lex.h>
  14. #include <sHT/test.h>
  15. #define def_str(m, a) char m[sizeof(a) - 1] = a
  16. /* Include some signed bytes as well,
  17. because <sHT/lex.c> used to pass potentially signed bytes
  18. to @var{sHT_bit_test}, which takes unsigned int.
  19. This is done by repeating the test with the bytes of @var{msg}
  20. and @var{c_allow} transposed from 0 to 128.
  21. This test case first had sign issues. On my x86-64 Linux system,
  22. signed/unsigned char did't really matter.
  23. GCC's -Werror=pointer-sign would have found the issue,
  24. although it gave no explanation. */
  25. static unsigned def_str(msg, "\x01\x02\x07\x03\x00\x05\x04\x03\x03");
  26. static unsigned char c_allow[64] = { 0b10111111 };
  27. static const unsigned char empty[53] = {};
  28. static enum {
  29. TRANSPOSED_NOT,
  30. TRANSPOSED,
  31. END,
  32. } transposed = 0;
  33. _Noreturn
  34. static size_t
  35. fail_cb()
  36. {
  37. if (transposed == TRANSPOSED_NOT) {
  38. if (printf("%s\n", "FAIL: fragmented/low") < 0)
  39. exit(2);
  40. if (printf("%s\n", "SKIP: fragmented/high") < 0)
  41. exit(2);
  42. exit(1);
  43. }
  44. if (printf("%s\n", "FAIL: fragmented/high\n") < 0)
  45. exit(2);
  46. exit(1);
  47. }
  48. static struct {
  49. struct sHT_lex_buf to;
  50. unsigned char bytes[53];
  51. } to = { .to = { .offset = 0 }, .bytes = { } };
  52. static struct sHT_lex_type c = {
  53. .cb_value = { &fail_cb, &fail_cb },
  54. .cb_ignore = &fail_cb,
  55. .c_allow = c_allow,
  56. .max_known = 30,
  57. .c_stop = 255,
  58. };
  59. static void
  60. more(size_t ret, size_t offset)
  61. {
  62. if (sHT_neq(sHT_lex(&to.to, msg + offset - ret, ret, &c), ret))
  63. fail_cb();
  64. /* Test offset incrementing */
  65. if (sHT_neq(to.to.offset, offset))
  66. fail_cb();
  67. size_t i;
  68. /* Correctly copied */
  69. sHT_index_iterate(i, offset) {
  70. if (sHT_neq(to.bytes[i], msg[i]))
  71. fail_cb();
  72. }
  73. /* Out-of-bound writes */
  74. if (memcmp(to.bytes + offset, empty, sizeof(to.bytes) - c.max_known))
  75. fail_cb();
  76. }
  77. _Noreturn
  78. static size_t
  79. expect_cb(struct sHT_lex_buf *arg_to, size_t n, size_t ret)
  80. {
  81. if (arg_to != &to.to)
  82. fail_cb();
  83. /* ... excluding the terminator */
  84. if (sHT_neq(n, 9 + 1))
  85. fail_cb();
  86. if (sHT_neq(ret, 2))
  87. fail_cb();
  88. /* Correctly copied */
  89. size_t i;
  90. sHT_index_iterate(i, 9u) {
  91. if (sHT_neq(to.bytes[i], msg[i]))
  92. fail_cb();
  93. }
  94. if (sHT_neq(to.bytes[9], transposed ? 131 : 4))
  95. fail_cb();
  96. /* Out-of-bound writes */
  97. if (memcmp(to.bytes + sizeof(to.bytes) - c.max_known, empty, sizeof(to.bytes) - c.max_known))
  98. fail_cb();
  99. if (transposed == TRANSPOSED_NOT) {
  100. if (printf("%s\n", "PASS: fragmented/low") < 2)
  101. exit(2);
  102. transposed = TRANSPOSED;
  103. } else if (transposed == END) {
  104. if (printf("%s\n", "PASS: fragmented/high") < 2)
  105. exit(2);
  106. exit(0);
  107. }
  108. /* Retry with all bytes > 127*/
  109. transposed = 1;
  110. sHT_index_iterate(i, sizeof(msg)) {
  111. msg[i] += 128;
  112. }
  113. c_allow[16] = c_allow[0];
  114. c_allow[0] = 0;
  115. c.cb_value[1] = &fail_cb;
  116. c.c_stop = 0x10;
  117. memset(&to, 0, sizeof(to));
  118. more(2u, 2u);
  119. more(3u, 5u);
  120. more(1u, 6u);
  121. more(3u, 9u);
  122. transposed = END;
  123. c.cb_value[1] = &expect_cb;
  124. /* cb_value[1] must be called -- well-formed */
  125. sHT_lex(&to.to, (unsigned char *) "\x83\x10", 2, &c);
  126. fail_cb();
  127. }
  128. int
  129. main(void)
  130. {
  131. more(2u, 2u);
  132. more(3u, 5u);
  133. more(1u, 6u);
  134. more(3u, 9u);
  135. c.cb_value[1] = &expect_cb;
  136. /* cb_value[1] must be called -- well-formed */
  137. sHT_lex(&to.to, (unsigned char *) "\x04\xff", 2, &c);
  138. fail_cb();
  139. }