Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [day] [month] [year] [list]
Message-Id: <53EF6890-9467-4886-8D98-C7050088AF0D@stasiak.at>
Date: Fri, 14 Jun 2024 00:59:41 +0200
From: Jakub Stasiak <jakub@...siak.at>
To: musl@...ts.openwall.com
Subject: [PATCH] inet_ntop: Fix the IPv6 leading zero sequence compression 

Per RFC 5952[1]:

    4.2.3.  Choice in Placement of "::"

       (...) When the length of the consecutive 16-bit 0 fields
       are equal (i.e., 2001:db8:0:0:1:0:0:1), the first sequence of zero
       bits MUST be shortened.  For example, 2001:db8::1:0:0:1 is correct
       representation.

but the implementation put the leading sequence of zeros at a
disadvantage. That's because for example when compressing

    0:0:0:10:0:0:0:10

the strspn(buf+i, ":0") call returns 6 for the first sequence and 7 for
the second one – the second sequence has the benefit of a leading
colon.

Because of that for this IPv6 input

    "\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x10"

inet_ntop produced

    0:0:0:10::10

instead of

    ::10:0:0:0:10

Changing the condition to require beating the leading sequence by not
one but two characters resolves the issue.

The new behavior is consistent with other implementations I tested
(glibc, Apple libc).

[1] https://www.rfc-editor.org/rfc/rfc5952#section-4.2.3
---
 src/network/inet_ntop.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/network/inet_ntop.c b/src/network/inet_ntop.c
index 4bfef2c557ab..37257cf9d787 100644
--- a/src/network/inet_ntop.c
+++ b/src/network/inet_ntop.c
@@ -34,7 +34,10 @@ const char *inet_ntop(int af, const void *restrict a0, char *restrict s, socklen
 		for (i=best=0, max=2; buf[i]; i++) {
 			if (i && buf[i] != ':') continue;
 			j = strspn(buf+i, ":0");
-			if (j>max) best=i, max=j;
+			// The leading sequence of zeros (best==0) is disadvantaged compared to
+			// sequences elsewhere as it doesn't have a leading colon. One extra
+			// character is required for another sequence to beat it fairly.
+			if (j>max+(best==0)) best=i, max=j;
 		}
 		if (max>3) {
 			buf[best] = buf[best+1] = ':';
-- 
2.45.1

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.