Refactor IPv6 zone ID parsing and reject malformed zone identifiers

This commit is contained in:
Frank Denis
2026-04-05 21:26:49 +02:00
parent 6b726ca29c
commit 1573e29bf3
2 changed files with 19 additions and 10 deletions
+15 -10
View File
@@ -485,29 +485,34 @@ sodium_ip2bin(unsigned char bin[16], const char *ip,
size_t ip_len_) /* Some AIX versions define a macro named "ip_len" */
{
const char *ip_end = ip + ip_len_;
const char *end;
const char *end = ip;
const char *zone = NULL;
const char *z;
unsigned char v4[4];
int is_ipv6;
for (end = ip; end < ip_end && *end != 0 && *end != '%'; end++) {
for (; end < ip_end && *end != 0; end++) {
/* empty */
}
if (end < ip_end && *end == '%') {
for (z = end + 1; z < ip_end && *z != 0; z++) {
if (isspace((unsigned char) *z)) {
zone = memchr(ip, '%', (size_t) (end - ip));
if (zone != NULL) {
for (z = zone + 1; z < end; z++) {
if (*z == '%' || isspace((unsigned char) *z)) {
return -1;
}
}
if (z == end + 1) {
if (zone + 1 >= end) {
return -1;
}
end = zone;
}
if (memchr(ip, ':', (size_t) (end - ip)) != NULL) {
return parse_ipv6(ip, end, bin) != 0 ? 0 : -1;
}
if (end < ip_end && *end == '%') {
is_ipv6 = memchr(ip, ':', (size_t) (end - ip)) != NULL;
if (zone != NULL && !is_ipv6) {
return -1;
}
if (is_ipv6) {
return parse_ipv6(ip, end, bin) != 0 ? 0 : -1;
}
if (parse_ipv4(ip, end, v4) == 0) {
return -1;
}
+4
View File
@@ -307,6 +307,10 @@ main(void)
assert(sodium_ip2bin(ip_bytes, "fe80::1%eth0", strlen("fe80::1%eth0")) == 0);
assert(sodium_ip2bin(ip_bytes, "fe80::1%15", strlen("fe80::1%15")) == 0);
assert(sodium_ip2bin(ip_bytes, "fe80::1%%eth0", strlen("fe80::1%%eth0")) == -1);
assert(sodium_ip2bin(ip_bytes, "fe80::1%eth0%1", strlen("fe80::1%eth0%1")) == -1);
assert(sodium_ip2bin(ip_bytes, "fe80::1%eth 0", strlen("fe80::1%eth 0")) == -1);
assert(sodium_ip2bin(ip_bytes, "192.168.1.1%eth0", strlen("192.168.1.1%eth0")) == -1);
printf("ip2bytes IPv6 zone: OK\n");
assert(sodium_ip2bin(ip_bytes, "2001:::1", strlen("2001:::1")) == -1);