From 78c3cebc389a2b0d426d74900a65b8656edb426d Mon Sep 17 00:00:00 2001 From: Dirk Engling Date: Mon, 26 Oct 2026 18:13:27 +0100 Subject: Third run of making variable and function names more readable, integer scans and ip parsers --- tests/t_ip.c | 54 +++++++++++----------- tests/t_scan.c | 124 ++++++++++++++++++++++++++++++++++++--------------- tests/t_urlencoded.c | 29 ------------ 3 files changed, 114 insertions(+), 93 deletions(-) (limited to 'tests') diff --git a/tests/t_ip.c b/tests/t_ip.c index 2fe3a72..8d71679 100644 --- a/tests/t_ip.c +++ b/tests/t_ip.c @@ -95,27 +95,27 @@ static void case_scan_forms(void) { char ip[16]; test_case("2.2 form 1, every group spelled out"); - CHECK_INT(ip_scan("1111:2222:3333:4444:5555:6666:7777:8888", ip), 39); + CHECK_INT(ip_parse("1111:2222:3333:4444:5555:6666:7777:8888", ip), 39); CHECK_MEM(ip, "\x11\x11\x22\x22\x33\x33\x44\x44\x55\x55\x66\x66\x77\x77\x88\x88", 16); test_case("2.2 form 2, zero groups abbreviated"); - CHECK_INT(ip_scan("2001:db8::1", ip), 11); + CHECK_INT(ip_parse("2001:db8::1", ip), 11); CHECK_MEM(ip, "\x20\x01\x0d\xb8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", 16); - CHECK_INT(ip_scan("::1", ip), 3); + CHECK_INT(ip_parse("::1", ip), 3); CHECK_MEM(ip, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", 16); - CHECK_INT(ip_scan("::", ip), 2); + CHECK_INT(ip_parse("::", ip), 2); CHECK_MEM(ip, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16); - CHECK_INT(ip_scan("1::", ip), 3); + CHECK_INT(ip_parse("1::", ip), 3); CHECK_MEM(ip, "\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16); test_case("2.2 form 3, a dotted quad in the last two groups"); - CHECK_INT(ip_scan("::ffff:1.2.3.4", ip), 14); + CHECK_INT(ip_parse("::ffff:1.2.3.4", ip), 14); CHECK_MEM(ip, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x01\x02\x03\x04", 16); - CHECK_INT(ip_scan("1:2:3:4:5:6:1.2.3.4", ip), 19); + CHECK_INT(ip_parse("1:2:3:4:5:6:1.2.3.4", ip), 19); CHECK_MEM(ip, "\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x01\x02\x03\x04", 16); test_case("upper case input is accepted"); - CHECK_INT(ip_scan("2001:DB8::1", ip), 11); + CHECK_INT(ip_parse("2001:DB8::1", ip), 11); CHECK_MEM(ip, "\x20\x01\x0d\xb8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", 16); } @@ -125,7 +125,7 @@ static void case_scan_accepts_bare_ipv4(void) { /* Every address opentracker holds is sixteen bytes, so an operator writing a plain IPv4 address in the config has to land as the v4 mapped form */ test_case("a bare IPv4 address is stored v4 mapped"); - CHECK_INT(ip_scan("10.0.0.1", ip), 8); + CHECK_INT(ip_parse("10.0.0.1", ip), 8); CHECK_MEM(ip, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x0a\x00\x00\x01", 16); CHECK(ip_is_v4mapped(ip)); } @@ -136,39 +136,39 @@ static void case_scan_reports_length(void) { /* The config parser continues from where the address ended, which is how "address:port" and "address/bits" are read */ test_case("scanning stops at the character after the address"); - CHECK_INT(ip_scan("10.0.0.1:6969", ip), 8); - CHECK_INT(ip_scan("2001:db8::1/64", ip), 11); - CHECK_INT(ip_scan("::1]", ip), 3); - CHECK_INT(ip_scan("1:2:3:4:5:6:7:8 trailing", ip), 15); + CHECK_INT(ip_parse("10.0.0.1:6969", ip), 8); + CHECK_INT(ip_parse("2001:db8::1/64", ip), 11); + CHECK_INT(ip_parse("::1]", ip), 3); + CHECK_INT(ip_parse("1:2:3:4:5:6:7:8 trailing", ip), 15); } static void case_scan_rejects(void) { char ip[16]; test_case("an empty or junk string is refused"); - CHECK_INT(ip_scan("", ip), 0); - CHECK_INT(ip_scan("x", ip), 0); - CHECK_INT(ip_scan(":", ip), 0); - CHECK_INT(ip_scan(":1:2", ip), 0); + CHECK_INT(ip_parse("", ip), 0); + CHECK_INT(ip_parse("x", ip), 0); + CHECK_INT(ip_parse(":", ip), 0); + CHECK_INT(ip_parse(":1:2", ip), 0); test_case("too few groups without :: are refused"); - CHECK_INT(ip_scan("1:2:3:4:5:6:7", ip), 0); - CHECK_INT(ip_scan("2001:db8:1", ip), 0); + CHECK_INT(ip_parse("1:2:3:4:5:6:7", ip), 0); + CHECK_INT(ip_parse("2001:db8:1", ip), 0); /* libowfat accepted a prefix of each of these and carried on. Taking only part of a malformed address is worse than refusing it, especially where the text comes from a config file or an X-Forwarded-For header. */ test_case("a second :: is refused rather than truncated"); - CHECK_INT(ip_scan("1::2::3", ip), 0); - CHECK_INT(ip_scan("::1::", ip), 0); - CHECK_INT(ip_scan("::::", ip), 0); + CHECK_INT(ip_parse("1::2::3", ip), 0); + CHECK_INT(ip_parse("::1::", ip), 0); + CHECK_INT(ip_parse("::::", ip), 0); test_case("more than eight groups is refused"); - CHECK_INT(ip_scan("1:2:3:4:5:6:7:8:9", ip), 0); + CHECK_INT(ip_parse("1:2:3:4:5:6:7:8:9", ip), 0); test_case("a group of more than four digits is refused, not truncated"); - CHECK_INT(ip_scan("12345::1", ip), 0); - CHECK_INT(ip_scan("fffff::1", ip), 0); + CHECK_INT(ip_parse("12345::1", ip), 0); + CHECK_INT(ip_parse("fffff::1", ip), 0); } static void case_round_trip(void) { @@ -187,7 +187,7 @@ static void case_round_trip(void) { test_case("every formatted address scans back to the same bytes"); for (i = 0; samples[i]; ++i) { - size_t n = ip_scan(samples[i], ip); + size_t n = ip_parse(samples[i], ip); if (n != strlen(samples[i])) { test_failf(__FILE__, __LINE__, "\"%s\" consumed %zu of %zu", samples[i], n, strlen(samples[i])); return; @@ -197,7 +197,7 @@ static void case_round_trip(void) { test_failf(__FILE__, __LINE__, "\"%s\" formatted back as \"%s\"", samples[i], text); return; } - if (!ip_scan(text, again) || memcmp(ip, again, 16)) { + if (!ip_parse(text, again) || memcmp(ip, again, 16)) { test_failf(__FILE__, __LINE__, "\"%s\" did not survive a second pass", samples[i]); return; } diff --git a/tests/t_scan.c b/tests/t_scan.c index 89f1590..aab4413 100644 --- a/tests/t_scan.c +++ b/tests/t_scan.c @@ -15,13 +15,13 @@ static void case_plain_numbers(void) { uint64_t value; test_case("a decimal number is read and its length reported"); - CHECK_INT(scan_udec("0", &value, 65535), 1); + CHECK_INT(scan_uint("0", &value, 65535), 1); CHECK_INT(value, 0); - CHECK_INT(scan_udec("7", &value, 65535), 1); + CHECK_INT(scan_uint("7", &value, 65535), 1); CHECK_INT(value, 7); - CHECK_INT(scan_udec("6969", &value, 65535), 4); + CHECK_INT(scan_uint("6969", &value, 65535), 4); CHECK_INT(value, 6969); - CHECK_INT(scan_udec("65535", &value, 65535), 5); + CHECK_INT(scan_uint("65535", &value, 65535), 5); CHECK_INT(value, 65535); } @@ -29,11 +29,11 @@ static void case_stops_at_non_digit(void) { uint64_t value; test_case("scanning stops at the first character that is not a digit"); - CHECK_INT(scan_udec("6969:rest", &value, 65535), 4); + CHECK_INT(scan_uint("6969:rest", &value, 65535), 4); CHECK_INT(value, 6969); - CHECK_INT(scan_udec("128/8", &value, 65535), 3); + CHECK_INT(scan_uint("128/8", &value, 65535), 3); CHECK_INT(value, 128); - CHECK_INT(scan_udec("42\n", &value, 65535), 2); + CHECK_INT(scan_uint("42\n", &value, 65535), 2); CHECK_INT(value, 42); } @@ -41,9 +41,9 @@ static void case_rejects_whitespace(void) { uint64_t value = 0xdead; test_case("leading whitespace is not skipped"); - CHECK_INT(scan_udec(" 1", &value, 65535), 0); - CHECK_INT(scan_udec("\t1", &value, 65535), 0); - CHECK_INT(scan_udec("\n1", &value, 65535), 0); + CHECK_INT(scan_uint(" 1", &value, 65535), 0); + CHECK_INT(scan_uint("\t1", &value, 65535), 0); + CHECK_INT(scan_uint("\n1", &value, 65535), 0); CHECK_INT(value, 0xdead); } @@ -51,9 +51,9 @@ static void case_rejects_sign(void) { uint64_t value = 0xdead; test_case("a sign is not accepted"); - CHECK_INT(scan_udec("+1", &value, 65535), 0); - CHECK_INT(scan_udec("-1", &value, 65535), 0); - CHECK_INT(scan_udec("-0", &value, 65535), 0); + CHECK_INT(scan_uint("+1", &value, 65535), 0); + CHECK_INT(scan_uint("-1", &value, 65535), 0); + CHECK_INT(scan_uint("-0", &value, 65535), 0); CHECK_INT(value, 0xdead); } @@ -61,9 +61,9 @@ static void case_rejects_empty_and_junk(void) { uint64_t value = 0xdead; test_case("a string with no leading digit yields nothing"); - CHECK_INT(scan_udec("", &value, 65535), 0); - CHECK_INT(scan_udec("x", &value, 65535), 0); - CHECK_INT(scan_udec(":80", &value, 65535), 0); + CHECK_INT(scan_uint("", &value, 65535), 0); + CHECK_INT(scan_uint("x", &value, 65535), 0); + CHECK_INT(scan_uint(":80", &value, 65535), 0); CHECK_INT(value, 0xdead); } @@ -71,9 +71,9 @@ static void case_no_alternative_bases(void) { uint64_t value; test_case("hexadecimal and octal notations are read as plain decimal"); - CHECK_INT(scan_udec("0x10", &value, 65535), 1); + CHECK_INT(scan_uint("0x10", &value, 65535), 1); CHECK_INT(value, 0); - CHECK_INT(scan_udec("010", &value, 65535), 3); + CHECK_INT(scan_uint("010", &value, 65535), 3); CHECK_INT(value, 10); } @@ -81,13 +81,13 @@ static void case_refuses_out_of_range(void) { uint64_t value = 0xdead; test_case("a value above max is refused, not truncated"); - CHECK_INT(scan_udec("65536", &value, 65535), 0); - CHECK_INT(scan_udec("99999", &value, 65535), 0); - CHECK_INT(scan_udec("129", &value, 128), 0); + CHECK_INT(scan_uint("65536", &value, 65535), 0); + CHECK_INT(scan_uint("99999", &value, 65535), 0); + CHECK_INT(scan_uint("129", &value, 128), 0); CHECK_INT(value, 0xdead); test_case("the boundary itself is accepted"); - CHECK_INT(scan_udec("128", &value, 128), 3); + CHECK_INT(scan_uint("128", &value, 128), 3); CHECK_INT(value, 128); } @@ -95,21 +95,21 @@ static void case_sixty_four_bit_range(void) { uint64_t value; test_case("the full unsigned 64 bit range is available"); - CHECK_INT(scan_udec("18446744073709551615", &value, UINT64_MAX), 20); + CHECK_INT(scan_uint("18446744073709551615", &value, UINT64_MAX), 20); CHECK(value == UINT64_MAX); test_case("a number too large for 64 bits is refused"); - CHECK_INT(scan_udec("18446744073709551616", &value, UINT64_MAX), 0); - CHECK_INT(scan_udec("99999999999999999999999999", &value, UINT64_MAX), 0); + CHECK_INT(scan_uint("18446744073709551616", &value, UINT64_MAX), 0); + CHECK_INT(scan_uint("99999999999999999999999999", &value, UINT64_MAX), 0); } static void case_leading_zeros_allowed(void) { uint64_t value; test_case("leading zeros are accepted outside bencode"); - CHECK_INT(scan_udec("007", &value, 65535), 3); + CHECK_INT(scan_uint("007", &value, 65535), 3); CHECK_INT(value, 7); - CHECK_INT(scan_udec("0000", &value, 65535), 4); + CHECK_INT(scan_uint("0000", &value, 65535), 4); CHECK_INT(value, 0); } @@ -117,9 +117,9 @@ static void case_bencode_rejects_leading_zeros(void) { uint64_t value = 0xdead; test_case("bencode refuses a leading zero on anything but zero"); - CHECK_INT(scan_udec_bencode("007", &value, 65535), 0); - CHECK_INT(scan_udec_bencode("0000", &value, 65535), 0); - CHECK_INT(scan_udec_bencode("01", &value, 65535), 0); + CHECK_INT(scan_uint_bencode("007", &value, 65535), 0); + CHECK_INT(scan_uint_bencode("0000", &value, 65535), 0); + CHECK_INT(scan_uint_bencode("01", &value, 65535), 0); CHECK_INT(value, 0xdead); } @@ -127,11 +127,11 @@ static void case_bencode_accepts_canonical(void) { uint64_t value; test_case("bencode accepts a canonically written number"); - CHECK_INT(scan_udec_bencode("0", &value, 65535), 1); + CHECK_INT(scan_uint_bencode("0", &value, 65535), 1); CHECK_INT(value, 0); - CHECK_INT(scan_udec_bencode("0:", &value, 65535), 1); + CHECK_INT(scan_uint_bencode("0:", &value, 65535), 1); CHECK_INT(value, 0); - CHECK_INT(scan_udec_bencode("160:", &value, 65535), 3); + CHECK_INT(scan_uint_bencode("160:", &value, 65535), 3); CHECK_INT(value, 160); } @@ -139,14 +139,64 @@ static void case_bencode_inherits_the_rest(void) { uint64_t value = 0xdead; test_case("bencode is no laxer than the plain scanner"); - CHECK_INT(scan_udec_bencode(" 1", &value, 65535), 0); - CHECK_INT(scan_udec_bencode("-1", &value, 65535), 0); - CHECK_INT(scan_udec_bencode("+1", &value, 65535), 0); - CHECK_INT(scan_udec_bencode("65536", &value, 65535), 0); + CHECK_INT(scan_uint_bencode(" 1", &value, 65535), 0); + CHECK_INT(scan_uint_bencode("-1", &value, 65535), 0); + CHECK_INT(scan_uint_bencode("+1", &value, 65535), 0); + CHECK_INT(scan_uint_bencode("65536", &value, 65535), 0); CHECK_INT(value, 0xdead); } +/* ------------------------------------------- fixed width signed integers */ + +/* A value lifted out of a query string arrives as a pointer and a length + with nothing terminating it, and the whole of it has to be the number. */ + +static void case_int_whole_field(void) { + int64_t value = 0; + + test_case("the whole field is read, sign and all"); + CHECK_INT(scan_int("123", 3, &value), 0); + CHECK_INT(value, 123); + CHECK_INT(scan_int("-45", 3, &value), 0); + CHECK_INT(value, -45); + + test_case("and only as far as the length given"); + CHECK_INT(scan_int("12345", 3, &value), 0); + CHECK_INT(value, 123); +} + +static void case_int_rejects_the_rest(void) { + int64_t value = 4711; + + test_case("anything that is not all digits is refused"); + CHECK_INT(scan_int("12a", 3, &value), -1); + CHECK_INT(scan_int("", 0, &value), -1); + CHECK_INT(scan_int("-", 1, &value), -1); + CHECK_INT(scan_int(" 12", 3, &value), -1); + CHECK_INT(scan_int("+12", 3, &value), -1); + + test_case("and a refused field leaves the number alone"); + CHECK_INT(value, 4711); +} + +static void case_int_overflow(void) { + int64_t value = 0; + + test_case("a field too long to fit is refused rather than wrapped"); + CHECK_INT(scan_int("9223372036854775807", 19, &value), 0); + CHECK_INT(value, INT64_MAX); + CHECK_INT(scan_int("9223372036854775808", 19, &value), -1); + CHECK_INT(scan_int("99999999999999999999", 20, &value), -1); + + test_case("including the negative side"); + CHECK_INT(scan_int("-9223372036854775807", 20, &value), 0); + CHECK_INT(value, -INT64_MAX); +} + void test_scan(void) { + case_int_whole_field(); + case_int_rejects_the_rest(); + case_int_overflow(); case_plain_numbers(); case_stops_at_non_digit(); case_rejects_whitespace(); diff --git a/tests/t_urlencoded.c b/tests/t_urlencoded.c index 1239e6b..6e0ee31 100644 --- a/tests/t_urlencoded.c +++ b/tests/t_urlencoded.c @@ -228,33 +228,6 @@ static void case_find_keywords(void) { CHECK_INT(urlencoded_match_keyword(keywords, &p, SCAN_SEARCHPATH_PARAM), -3); } -static void case_fixed_int(void) { - char positive[] = "123"; - char negative[] = "-45"; - char trailing[] = "12a"; - int value; - - test_case("scan_fixed_int returns the count of unparsed bytes"); - CHECK_INT(scan_fixed_int(positive, 3, &value), 0); - CHECK_INT(value, 123); - - CHECK_INT(scan_fixed_int(negative, 3, &value), 0); - CHECK_INT(value, -45); - - CHECK_INT(scan_fixed_int(trailing, 3, &value), 1); - CHECK_INT(value, 12); -} - -static void case_fixed_int_bounded(void) { - char digits[] = "12345"; - int value; - - test_case("scan_fixed_int honours the length it is given"); - CHECK_INT(scan_fixed_int(digits, 3, &value), 0); - CHECK_INT(value, 123); -} - - /* The encoding direction. Which bytes survive unescaped is fixed by what existing parsers of the urlencoded full scrape expect, so these cases pin the set rather than describe a preference. */ @@ -361,8 +334,6 @@ void test_urlencoded(void) { case_raw_high_byte(); case_skipvalue(); case_find_keywords(); - case_fixed_int(); - case_fixed_int_bounded(); case_fmt_passes_safe_bytes(); case_fmt_escapes_the_rest(); case_fmt_hex_is_lower_case(); -- cgit v1.3