diff --git a/src/isinetaddr6.c b/src/isinetaddr6.c index 6db4af8..0aeaddf 100644 --- a/src/isinetaddr6.c +++ b/src/isinetaddr6.c @@ -11,6 +11,7 @@ static const char SEP = ':'; static int has_consecutive_chars(const char *str, char c, int n); static char* expand(const char *str, size_t strlen, char *new_str, size_t headlen); +static size_t get_offset(char *tail); int isinetaddr6(const char *str) @@ -66,10 +67,12 @@ static char* expand(const char *str, size_t strlen, char *new_str, size_t headlen) { char *ptr = new_str; + char *tail = (char*) &str[headlen + 2]; size_t taillen = (strlen - headlen) - 2; size_t bodylen = MAX_STRLEN - taillen; size_t i = headlen + 2; size_t j = headlen; + size_t offset = get_offset(tail); while (i++ < strlen) { if (has_consecutive_chars(&str[i], SEP, 2)) { @@ -78,9 +81,23 @@ expand(const char *str, size_t strlen, char *new_str, size_t headlen) } memcpy(ptr, &str[0], headlen); ptr += headlen; - while (++j < bodylen) { + while (++j < bodylen-offset) { *ptr++ = j % 5 == 0 ? ':' : '0'; } - memcpy(ptr, &str[headlen + 2], taillen); + memcpy(ptr, tail, taillen); return new_str; } + +static size_t +get_offset(char *tail) +{ + size_t offset = 0; + while (*tail++ != SEP) { + offset++; + if (*tail == '\0' || offset == 4) { + offset = 0; + break; + } + } + return offset; +} diff --git a/test/isinetaddr6_test.c b/test/isinetaddr6_test.c index 82065f5..2ac220f 100644 --- a/test/isinetaddr6_test.c +++ b/test/isinetaddr6_test.c @@ -22,6 +22,7 @@ const char *valid[] = { "2001:DB8:0:0:8:800:200C:417A", /* valid IPv6 (double colon) */ + "2001:DB8::8:800:200C:417A", "fe80::c001:a0ff:fe12:3456", "2001:0db8::1", "2001:abcd:ef01:2345::",