123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- // SPDX-License-Identifier: GPL-2.0 or GPL-3.0
- // Copyright © 2018-2019 Ariadne Devos
- /* sHT -- test the lexer for Kleene closures of letter sets */
- /** Testing fragmentation in the lexer
- The HTTP header name can theoretically be fragmented, but typically,
- it isn't. Test fragmentation specially. TODO: test too long lexemes,
- unless it's common in some situation in s2. */
- #include <stddef.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sHT/index.h>
- #include <sHT/lex.h>
- #include <sHT/test.h>
- #define def_str(m, a) char m[sizeof(a) - 1] = a
- /* Include some signed bytes as well,
- because <sHT/lex.c> used to pass potentially signed bytes
- to @var{sHT_bit_test}, which takes unsigned int.
- This is done by repeating the test with the bytes of @var{msg}
- and @var{c_allow} transposed from 0 to 128.
- This test case first had sign issues. On my x86-64 Linux system,
- signed/unsigned char did't really matter.
- GCC's -Werror=pointer-sign would have found the issue,
- although it gave no explanation. */
- static unsigned def_str(msg, "\x01\x02\x07\x03\x00\x05\x04\x03\x03");
- static unsigned char c_allow[64] = { 0b10111111 };
- static const unsigned char empty[53] = {};
- static enum {
- TRANSPOSED_NOT,
- TRANSPOSED,
- END,
- } transposed = 0;
- _Noreturn
- static size_t
- fail_cb()
- {
- if (transposed == TRANSPOSED_NOT) {
- if (printf("%s\n", "FAIL: fragmented/low") < 0)
- exit(2);
- if (printf("%s\n", "SKIP: fragmented/high") < 0)
- exit(2);
- exit(1);
- }
- if (printf("%s\n", "FAIL: fragmented/high\n") < 0)
- exit(2);
- exit(1);
- }
- static struct {
- struct sHT_lex_buf to;
- unsigned char bytes[53];
- } to = { .to = { .offset = 0 }, .bytes = { } };
- static struct sHT_lex_type c = {
- .cb_value = { &fail_cb, &fail_cb },
- .cb_ignore = &fail_cb,
- .c_allow = c_allow,
- .max_known = 30,
- .c_stop = 255,
- };
- static void
- more(size_t ret, size_t offset)
- {
- if (sHT_neq(sHT_lex(&to.to, msg + offset - ret, ret, &c), ret))
- fail_cb();
- /* Test offset incrementing */
- if (sHT_neq(to.to.offset, offset))
- fail_cb();
- size_t i;
- /* Correctly copied */
- sHT_index_iterate(i, offset) {
- if (sHT_neq(to.bytes[i], msg[i]))
- fail_cb();
- }
- /* Out-of-bound writes */
- if (memcmp(to.bytes + offset, empty, sizeof(to.bytes) - c.max_known))
- fail_cb();
- }
- _Noreturn
- static size_t
- expect_cb(struct sHT_lex_buf *arg_to, size_t n, size_t ret)
- {
- if (arg_to != &to.to)
- fail_cb();
- /* ... excluding the terminator */
- if (sHT_neq(n, 9 + 1))
- fail_cb();
- if (sHT_neq(ret, 2))
- fail_cb();
- /* Correctly copied */
- size_t i;
- sHT_index_iterate(i, 9u) {
- if (sHT_neq(to.bytes[i], msg[i]))
- fail_cb();
- }
- if (sHT_neq(to.bytes[9], transposed ? 131 : 4))
- fail_cb();
- /* Out-of-bound writes */
- if (memcmp(to.bytes + sizeof(to.bytes) - c.max_known, empty, sizeof(to.bytes) - c.max_known))
- fail_cb();
- if (transposed == TRANSPOSED_NOT) {
- if (printf("%s\n", "PASS: fragmented/low") < 2)
- exit(2);
- transposed = TRANSPOSED;
- } else if (transposed == END) {
- if (printf("%s\n", "PASS: fragmented/high") < 2)
- exit(2);
- exit(0);
- }
- /* Retry with all bytes > 127*/
- transposed = 1;
- sHT_index_iterate(i, sizeof(msg)) {
- msg[i] += 128;
- }
- c_allow[16] = c_allow[0];
- c_allow[0] = 0;
- c.cb_value[1] = &fail_cb;
- c.c_stop = 0x10;
- memset(&to, 0, sizeof(to));
- more(2u, 2u);
- more(3u, 5u);
- more(1u, 6u);
- more(3u, 9u);
- transposed = END;
- c.cb_value[1] = &expect_cb;
- /* cb_value[1] must be called -- well-formed */
- sHT_lex(&to.to, (unsigned char *) "\x83\x10", 2, &c);
- fail_cb();
- }
- int
- main(void)
- {
- more(2u, 2u);
- more(3u, 5u);
- more(1u, 6u);
- more(3u, 9u);
- c.cb_value[1] = &expect_cb;
- /* cb_value[1] must be called -- well-formed */
- sHT_lex(&to.to, (unsigned char *) "\x04\xff", 2, &c);
- fail_cb();
- }
|