123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- // SPDX-License-Identifier: GPL-2.0 or GPL-3.0
- // Copyright © 2019 Ariadne Devos
- #include <stdbool.h>
- #include <stddef.h>
- #include <stdint.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <sHT/logic/failbit.h>
- #include <sHT/lex/ipv4-addr.h>
- #define BADIP UINT32_C(0)
- #define success(a) sHT_success_const(a)
- #define failure(a) sHT_fail_const(a)
- static const struct testcase
- {
- uint8_t m[32];
- size_t length;
- sHT_with_failbit
- size_t end;
- uint32_t ip;
- } cases[] = {
- /* mappend, first digit, last digit*/
- { "_0.0.0.19", 8, success(8), UINT32_C(0x00000001) },
- { "_1.0.0.79", 8, success(8), UINT32_C(0x01000007) },
- { "_2.0.0.29", 8, success(8), UINT32_C(0x02000002) },
- { "_9.0.0.39", 8, success(8), UINT32_C(0x09000003) },
- /* large digits */
- { "_255.250.199.99", 15, success(16), UINT32_C(0xfffac763) },
- { "_99.255.250.199", 15, success(16), UINT32_C(0x63fffac7) },
- { "_199.99.255.250", 15, success(16), UINT32_C(0xc763fffa) },
- { "_199.99.99.2500", 15, success(15), UINT32_C(0xc763fffa) },
- { "_256.250.199.99", 15, failure(15), BADIP },
- { "_255.260.199.99", 15, failure(15), BADIP },
- { "_255.300.199.99", 15, failure(15), BADIP },
- { "_25@.250.199.99", 15, failure(3), BADIP },
- { "_255.250.199.@9", 15, failure(13), BADIP },
- { "_255@250.199.99", 15, failure(4), BADIP },
- /* leading zeroes */
- { "_01.23.23.23", 12, failure(12), BADIP },
- { "_10.023.23.23", 13, failure(13), BADIP },
- { "_10.003.23.23", 13, failure(13), BADIP },
- { "_10.000.23.23", 13, failure(13), BADIP },
- { "_10.0000.23.23", 14, failure(14), BADIP },
- /* overly many repetitions */
- { "_255.250.199.99.20", 18, success(16), UINT32_C(0xfffac763) },
- { "_99.255.250.199.20", 18, success(16), UINT32_C(0x63fffac7) },
- { "_199.99.255.250.20", 18, success(16), UINT32_C(0xc763fffa) },
- { "_199.99.99.2500.20", 18, success(15), UINT32_C(0xc763fffa) },
- { "_255.250.199.99@20", 18, success(16), UINT32_C(0xfffac763) },
- { "_99.255.250.199@20", 18, success(16), UINT32_C(0x63fffac7) },
- { "_199.99.255.250@20", 18, success(16), UINT32_C(0xc763fffa) },
- { "_199.99.99.2500@20", 18, success(15), UINT32_C(0xc763fffa) },
- /* off-by-one digit tests */
- { "_0.0.0.0", 8, success(8), UINT32_C(0x00000000) },
- { "_1.0.0.0", 8, success(8), UINT32_C(0x01000000) },
- { "_2.0.0.0", 8, success(8), UINT32_C(0x02000000) },
- { "_9.0.0.0", 8, success(8), UINT32_C(0x09000000) },
- { "_/.0.0.0", 8, failure(1), BADIP },
- { "_:.0.0.0", 8, failure(1), BADIP },
- { "_1/.0.0.0", 9, failure(2), BADIP },
- { "_1:.0.0.0", 9, failure(2), BADIP },
- { "_10/.0.0.0", 10, failure(3), BADIP },
- { "_10:.0.0.0", 10, failure(3), BADIP },
- /* Check 2 > length - i.
- (The trailing octet is not within specified bounds,
- so it may not be parsed, as is the leading '0')
- In case of 1 > length - i, the first digit of the last octet
- is accessed out-of-bounds, but that's ‘corrected’ by
- sHT_index_nospec to the first byte of the string*/
- { "01.2.3.", 7, failure(7), BADIP },
- { "01.2.30.", 7, failure(7), BADIP },
- { "01.2.30.", 7, failure(7), BADIP },
- { "010.2.3.", 8, failure(8), BADIP },
- { "010.2.30.", 8, failure(8), BADIP },
- { "010.20.3.", 9, failure(9), BADIP },
- { "010.20.30.", 9, failure(9), BADIP },
- { "010.20.25.", 10, failure(10), BADIP },
- { "010.20.255.", 10, failure(10), BADIP },
- { "010.20.254.", 11, failure(11), BADIP },
- { "010.20.255.", 11, failure(11), BADIP },
- { "010.20.256.", 11, failure(11), BADIP },
- /* too early EOF */
- { "_0.0.255.", 9, failure(10), BADIP },
- { "_0.0.20.", 8, failure(9), BADIP },
- { "_20.0.0.", 8, failure(9), BADIP },
- { "_0.10.255", 9, failure(10), BADIP },
- { "_0.10.20", 8, failure(9), BADIP },
- { "_20.10.0", 8, failure(9), BADIP },
- /* empty */
- { "0", 1, failure(1), BADIP },
- { "_", 1, failure(1), BADIP },
- { "_0", 2, failure(2), BADIP },
- { "_0.", 3, failure(3), BADIP },
- { "_0.1", 4, failure(4), BADIP },
- { "_0.12", 5, failure(5), BADIP },
- { "_0.12.", 6, failure(6), BADIP },
- { "_0.12.2", 7, failure(8), BADIP },
- };
- #define ARRAY_SIZE(a) ((sizeof(a) / sizeof(*(a))))
- #ifdef __FRAMAC__
- # define _Noreturn
- #endif
- _Noreturn void
- fail(size_t i)
- {
- if (printf("FAIL: ipv4 (%d)\n", (unsigned) i) < 0)
- exit(2);
- exit(1);
- }
- int
- main(void)
- {
- for (size_t i = 0; i < ARRAY_SIZE(cases); i++) {
- struct s2_ipv4_maybe ret;
- ret = s2_parse_ipv4(cases[i].length, cases[i].m);
- /* out-of-bounds */
- if (sHT_fail_value(ret.end) > cases[i].length)
- fail(i);
- if (sHT_bad(ret.end)) {
- if (sHT_good(cases[i].end))
- fail(i);
- /* (z): *at least* up to (>, not =) fail_value(ret.end), [0-9.] */
- if (sHT_fail_value(ret.end) > sHT_fail_value(cases[i].end))
- fail(i);
- goto compare_longer_inputs;
- }
- /* Synthetise input from output, check with reference input*/
- char ipcheck[32];
- if (sHT_fail_value(ret.end) - 1 != (size_t) sprintf(ipcheck, "%d.%d.%d.%d", ret.ip >> 24, (ret.ip >> 16) & 0xff, (ret.ip >> 8) & 0xff, ret.ip & 0xff))
- /* length does not agree */
- fail(i);
- if (memcmp(cases[i].m + 1, ipcheck, sHT_fail_value(ret.end) - 1)) {
- /* bytes do not agree */
- fail(i);
- }
- compare_longer_inputs:
- for (size_t d = sHT_fail_value(ret.end) + 1; d <= sHT_fail_value(cases[i].length); d++) {
- struct s2_ipv4_maybe alt = s2_parse_ipv4(d, cases[i].m);
- /* Check failbit for equality */
- if ((ret.end ^ alt.end) & sHT_failbit_limit)
- fail(i);
- /* Check parsing doesn't end too late */
- if (sHT_fail_value(alt.end) <= sHT_fail_value(cases[i].end))
- /* If at all, there is only one way to parse it. */
- if (sHT_good(ret.end) && (ret.end != alt.end))
- fail(i);
- /* Check numeric IPv4Address */
- if (sHT_good(ret.end) && (ret.ip != alt.ip))
- fail(i);
- }
- }
- if (printf("PASS: ipv4\n") < 2)
- exit(2);
- return 0;
- }
|