From: dongshengyuan <545258830@qq.com> Date: Mon, 22 Jun 2026 05:16:32 +0000 (+0800) Subject: oci-util: fix and harden oci_registry_is_valid() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7020bd3d8295994e46a24ff8819d5117abb34db6;p=thirdparty%2Fsystemd.git oci-util: fix and harden oci_registry_is_valid() - Pass colon+1 (port string) instead of s (hostname) to safe_atou16, so host:port registries are no longer always rejected. - Switch to safe_atou16_full() with base-10 and strict flags to reject non-decimal port forms (hex, octal, leading whitespace, sign prefix) that would produce malformed URL authorities. - Reject empty host explicitly via isempty() guard (covers both NULL and empty-string input), and guard colon == n to reject ':port' form, since dns_name_is_valid('') == 1 (DNS root) would otherwise accept empty host as valid. - Wrap overlong line to fit 109-column limit. - Add test coverage for oci_registry_is_valid(). Signed-off-by: dongshengyuan --- diff --git a/src/import/oci-util.c b/src/import/oci-util.c index d8c16bc3d97..a3c5782e989 100644 --- a/src/import/oci-util.c +++ b/src/import/oci-util.c @@ -51,13 +51,16 @@ bool oci_image_is_valid(const char *n) { int oci_registry_is_valid(const char *n) { int r; - if (!n) + if (isempty(n)) return false; const char *colon = strchr(n, ':'); if (!colon) return dns_name_is_valid(n); + if (colon == n) /* empty host, e.g. ":5000" */ + return false; + _cleanup_free_ char *s = strndup(n, colon - n); if (!s) return -ENOMEM; @@ -67,7 +70,10 @@ int oci_registry_is_valid(const char *n) { return r; uint16_t port; - return safe_atou16(s, &port) >= 0 && port != 0; + return safe_atou16_full(colon + 1, + 10 | SAFE_ATO_REFUSE_LEADING_WHITESPACE | + SAFE_ATO_REFUSE_PLUS_MINUS | SAFE_ATO_REFUSE_LEADING_ZERO, + &port) >= 0 && port != 0; } bool oci_tag_is_valid(const char *n) { diff --git a/src/import/test-oci-util.c b/src/import/test-oci-util.c index 395b622b428..3fa62eb1b5b 100644 --- a/src/import/test-oci-util.c +++ b/src/import/test-oci-util.c @@ -19,4 +19,33 @@ TEST(urlescape) { test_urlescape_one("müffel", "m%c3%bcffel"); } +TEST(oci_registry_is_valid) { + /* plain hostname — valid */ + assert_se(oci_registry_is_valid("localhost") > 0); + assert_se(oci_registry_is_valid("registry.example.com") > 0); + + /* host:port — valid */ + assert_se(oci_registry_is_valid("localhost:5000") > 0); + assert_se(oci_registry_is_valid("registry.example.com:443") > 0); + assert_se(oci_registry_is_valid("registry.io:1") > 0); + assert_se(oci_registry_is_valid("registry.io:65535") > 0); + + /* port 0 — invalid */ + assert_se(oci_registry_is_valid("localhost:0") == 0); + + /* port overflow */ + assert_se(oci_registry_is_valid("localhost:65536") == 0); + + /* non-decimal port forms — rejected */ + assert_se(oci_registry_is_valid("localhost:0x50") == 0); /* hex */ + assert_se(oci_registry_is_valid("localhost:017") == 0); /* leading zero */ + assert_se(oci_registry_is_valid("localhost:+80") == 0); /* plus sign */ + assert_se(oci_registry_is_valid("localhost: 80") == 0); /* leading space */ + + /* invalid hostname */ + assert_se(oci_registry_is_valid(":5000") == 0); + assert_se(oci_registry_is_valid("") == 0); + assert_se(oci_registry_is_valid(NULL) == 0); +} + DEFINE_TEST_MAIN(LOG_DEBUG);