From 8fd480584e5eee7b60125e6ca89a51cdd93e7e77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20R=C3=BChsen?= Date: Fri, 23 Feb 2018 12:09:03 +0100 Subject: [PATCH] Fix PSL_TYPE_NO_STAR_RULE and improve test suite Reported-by: Daniel Kahn Gillmor --- src/psl.c | 6 +- tests/test-is-public-all.c | 129 +++++++++++++++++---------------- tests/test-is-public-builtin.c | 3 + tests/test-is-public.c | 3 + 4 files changed, 77 insertions(+), 64 deletions(-) diff --git a/src/psl.c b/src/psl.c index 6ff7271..7d1c411 100644 --- a/src/psl.c +++ b/src/psl.c @@ -841,12 +841,12 @@ static int _psl_is_public_suffix(const psl_ctx_t *psl, const char *domain, int t if (suffix.nlabels == 1) { /* TLD, this is the prevailing '*' match. If type excludes the '*' rule, continue. */ - if (type & PSL_TYPE_NO_STAR_RULE) - type &= ~PSL_TYPE_NO_STAR_RULE; - else + if (!(type & PSL_TYPE_NO_STAR_RULE)) return 1; } + type &= ~PSL_TYPE_NO_STAR_RULE; + if (psl->utf8 || psl == &_builtin_psl) need_conversion = 0; diff --git a/tests/test-is-public-all.c b/tests/test-is-public-all.c index 982775b..6a317ac 100644 --- a/tests/test-is-public-all.c +++ b/tests/test-is-public-all.c @@ -54,77 +54,84 @@ static int _isspace_ascii(const char c) return c == ' ' || c == '\t' || c == '\r' || c == '\n'; } +static const char *_type_string(int type) +{ + switch (type) { + case PSL_TYPE_ANY: return "PSL_TYPE_ANY"; + case PSL_TYPE_PRIVATE: return "PSL_TYPE_PRIVATE"; + case PSL_TYPE_ICANN: return "PSL_TYPE_ICANN"; + case PSL_TYPE_ANY|PSL_TYPE_NO_STAR_RULE: return "PSL_TYPE_ANY|PSL_TYPE_NO_STAR_RULE"; + case PSL_TYPE_PRIVATE|PSL_TYPE_NO_STAR_RULE: return "PSL_TYPE_PRIVATE|PSL_TYPE_NO_STAR_RULE"; + case PSL_TYPE_ICANN|PSL_TYPE_NO_STAR_RULE: return "PSL_TYPE_ICANN|PSL_TYPE_NO_STAR_RULE"; + default: return "Unsupported type"; + } +} + +static void test_ps(const psl_ctx_t *psl, const char *domain, int type, int expected) +{ + int result; + + if ((result = psl_is_public_suffix2(psl, domain, type)) != expected) { + failed++; + printf("psl_is_public_suffix2(%s, %s)=%d (expected %d)\n", domain, _type_string(type), result, expected); + } else ok++; +} + +/* section: either PSL_TYPE_PRIVATE or PSL_TYPE_ICANN */ +static void test_type_any(const psl_ctx_t *psl, const char *domain, int type, int expected) +{ + int result; + int wildcard = (*domain == '.'); + int tld = !(strchr(domain + wildcard, '.')); + + test_ps(psl, domain, type, expected); + test_ps(psl, domain, type|PSL_TYPE_NO_STAR_RULE, expected); + test_ps(psl, domain, PSL_TYPE_ANY, expected); + test_ps(psl, domain, PSL_TYPE_ANY|PSL_TYPE_NO_STAR_RULE, expected); + + if (type == PSL_TYPE_PRIVATE) { + if (tld) { + test_ps(psl, domain, PSL_TYPE_ICANN, 1); + test_ps(psl, domain, PSL_TYPE_ICANN|PSL_TYPE_NO_STAR_RULE, 0); + } else { + test_ps(psl, domain, PSL_TYPE_ICANN, 0); + test_ps(psl, domain, PSL_TYPE_ICANN|PSL_TYPE_NO_STAR_RULE, 0); + } + } else if (type == PSL_TYPE_ICANN) { + if (tld) { + test_ps(psl, domain, PSL_TYPE_PRIVATE, 1); + test_ps(psl, domain, PSL_TYPE_PRIVATE|PSL_TYPE_NO_STAR_RULE, 0); + } else { + test_ps(psl, domain, PSL_TYPE_PRIVATE, 0); + test_ps(psl, domain, PSL_TYPE_PRIVATE|PSL_TYPE_NO_STAR_RULE, 0); + } + } +} + static void test_psl_entry(const psl_ctx_t *psl, const char *domain, int type) { int result; if (*domain == '!') { /* an exception to a wildcard, e.g. !www.ck (wildcard is *.ck) */ - if ((result = psl_is_public_suffix(psl, domain + 1))) { - failed++; - printf("psl_is_public_suffix(%s)=%d (expected 0)\n", domain, result); - } else ok++; + test_type_any(psl, domain + 1, type, 0); /* the exception itself is not a PS */ + + if ((domain = strchr(domain, '.'))) + test_type_any(psl, domain, type, 1); /* the related wildcard domain is a PS */ - if ((domain = strchr(domain, '.'))) { - if (!(result = psl_is_public_suffix(psl, domain + 1))) { - failed++; - printf("psl_is_public_suffix(%s)=%d (expected 1)\n", domain + 1, result); - } else ok++; - } } else if (*domain == '*') { /* a wildcard, e.g. *.ck or *.platform.sh */ - char *xdomain; - size_t len; + /* '*.platform.sh' -> 'y.x.platform.sh' */ + size_t len = strlen(domain); + char *xdomain = alloca(len + 3); - if (!(result = psl_is_public_suffix(psl, domain + 1))) { - failed++; - printf("psl_is_public_suffix(%s)=%d (expected 1)\n", domain + 1, result); - } else ok++; + memcpy(xdomain, "y.x", 3); + memcpy(xdomain + 3, domain + 1, len); + + test_type_any(psl, domain + 1, type, 1); /* the domain without wildcard is a PS */ + test_type_any(psl, xdomain + 2, type, 1); /* random wildcard-matching domain is a PS... */ + test_type_any(psl, xdomain, type, 0); /* ... but sub domain is not */ - len = strlen(domain); - xdomain = alloca(len + 1); - memcpy(xdomain, domain, len + 1); - *xdomain = 'x'; - if (!(result = psl_is_public_suffix(psl, domain))) { - failed++; - printf("psl_is_public_suffix(%s)=%d (expected 1)\n", domain, result); - } else ok++; } else { - if (!(result = psl_is_public_suffix(psl, domain))) { - failed++; - printf("psl_is_public_suffix(%s)=%d (expected 1)\n", domain, result); - } else ok++; - - if (!(strchr(domain, '.'))) { - /* TLDs are always expected to be Public Suffixes */ - if (!(result = psl_is_public_suffix2(psl, domain, PSL_TYPE_PRIVATE))) { - failed++; - printf("psl_is_public_suffix2(%s, PSL_TYPE_PRIVATE)=%d (expected 1)\n", domain, result); - } else ok++; - - if (!(result = psl_is_public_suffix2(psl, domain, PSL_TYPE_ICANN))) { - failed++; - printf("psl_is_public_suffix2(%s, PSL_TYPE_ICANN)=%d (expected 0)\n", domain, result); - } else ok++; - } else if (type == PSL_TYPE_PRIVATE) { - if (!(result = psl_is_public_suffix2(psl, domain, PSL_TYPE_PRIVATE))) { - failed++; - printf("psl_is_public_suffix2(%s, PSL_TYPE_PRIVATE)=%d (expected 1)\n", domain, result); - } else ok++; - - if ((result = psl_is_public_suffix2(psl, domain, PSL_TYPE_ICANN))) { - failed++; - printf("psl_is_public_suffix2(%s, PSL_TYPE_ICANN)=%d (expected 0)\n", domain, result); - } else ok++; - } else if (type == PSL_TYPE_ICANN) { - if (!(result = psl_is_public_suffix2(psl, domain, PSL_TYPE_ICANN))) { - failed++; - printf("psl_is_public_suffix2(%s, PSL_TYPE_ICANN)=%d (expected 1)\n", domain, result); - } else ok++; - - if ((result = psl_is_public_suffix2(psl, domain, PSL_TYPE_PRIVATE))) { - failed++; - printf("psl_is_public_suffix2(%s, PSL_TYPE_PRIVATE)=%d (expected 0)\n", domain, result); - } else ok++; - } + test_type_any(psl, domain, type, 1); /* Any normal PSL entry */ } } diff --git a/tests/test-is-public-builtin.c b/tests/test-is-public-builtin.c index a631dbe..59f4016 100644 --- a/tests/test-is-public-builtin.c +++ b/tests/test-is-public-builtin.c @@ -90,6 +90,9 @@ static void test_psl(void) { "", 1, 0 }, /* special case */ { NULL, 1, 1 }, /* special case */ { "adfhoweirh", 1, 0 }, /* unknown TLD */ + { "compute.amazonaws.com", 1, 1 }, /* special rule *.compute.amazonaws.com */ + { "y.compute.amazonaws.com", 1, 1 }, + { "x.y.compute.amazonaws.com", 0, 0 }, }; unsigned it; const psl_ctx_t *psl; diff --git a/tests/test-is-public.c b/tests/test-is-public.c index 6c6c5a1..5ef14cc 100644 --- a/tests/test-is-public.c +++ b/tests/test-is-public.c @@ -84,6 +84,9 @@ static void test_psl(void) { "", 1, 0 }, /* special case */ { NULL, 1, 1 }, /* special case */ { "adfhoweirh", 1, 0 }, /* unknown TLD */ + { "compute.amazonaws.com", 1, 1 }, /* special rule *.compute.amazonaws.com */ + { "y.compute.amazonaws.com", 1, 1 }, + { "x.y.compute.amazonaws.com", 0, 0 }, }; unsigned it; int result, ver;