]> git.ipfire.org Git - thirdparty/ipset.git/commitdiff
Listing/saving of large sets could produce broken listing, fixed.
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Thu, 23 Dec 2010 13:33:16 +0000 (14:33 +0100)
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Thu, 23 Dec 2010 13:33:16 +0000 (14:33 +0100)
The wrapper around getnameinfo was not snprintf-compatible and
that could cause broken listing/saving for large sets.

lib/print.c
lib/session.c

index 767fd044634facc3e2ff8c3091dfc16d7eb1cf0e..b6819e54fa198e4e7b1957c8f81e603edb5a0f97 100644 (file)
@@ -162,7 +162,9 @@ __getnameinfo##f(char *buf, unsigned int len,                               \
                                  sizeof(saddr),                        \
                                  buf, len, NULL, 0,                    \
                                  flags | NI_NUMERICHOST);              \
-       return (err != 0 ? -1 : (int)strlen(buf));                      \
+       D("getnameinfo err: %i, errno %i", err, errno);                 \
+       return (err == 0 ? (int)strlen(buf) :                           \
+              (err == EAI_OVERFLOW || err == EAI_SYSTEM) ? (int)len : -1);\
 }
 
 #define SNPRINTF_IP(mask, f)                                           \
@@ -236,6 +238,7 @@ ipset_print_ip(char *buf, unsigned int len,
                size = snprintf_ipv6(buf, len, flags, ip, cidr);
        else
                return -1;
+       D("size %i, len %u", size, len);
        SNPRINTF_FAILURE(size, len, offset);
 
        D("len: %u, offset %u", len, offset);
index 4a08b94ddf4638b9970e58226e0454d9cfc64208..2a57378a15077a8d0fa35bd62d17039e476c9d12 100644 (file)
@@ -636,9 +636,10 @@ safe_snprintf(struct ipset_session *session, const char *fmt, ...)
        int len, ret, loop = 0;
 
 retry:
-       len = IPSET_OUTBUFLEN - strlen(session->outbuf);
+       len = strlen(session->outbuf);
+       D("len: %u, retry %u", len, loop);
        va_start(args, fmt);
-       ret = vsnprintf(session->outbuf + IPSET_OUTBUFLEN - len, len,
+       ret = vsnprintf(session->outbuf + len, IPSET_OUTBUFLEN - len,
                        fmt, args);
        va_end(args);
        
@@ -646,13 +647,14 @@ retry:
                return ipset_err(session,
                                 "Internal error at printing to output buffer");
 
-       if (ret >= len) {
+       if (ret >= IPSET_OUTBUFLEN - len) {
                /* Buffer was too small, push it out and retry */
+               D("print buffer and try again: %u", len);
                if (loop++)
                        return ipset_err(session,
                                "Internal error at printing, loop detected!");
 
-               session->outbuf[IPSET_OUTBUFLEN - len] = '\0';
+               session->outbuf[len] = '\0';
                if (!call_outfn(session))
                        goto retry;
        }
@@ -666,21 +668,23 @@ safe_dprintf(struct ipset_session *session, ipset_printfn fn,
        int len, ret, loop = 0;
 
 retry:
-       len = IPSET_OUTBUFLEN - strlen(session->outbuf);
-       ret = fn(session->outbuf + IPSET_OUTBUFLEN - len, len,
+       len = strlen(session->outbuf);
+       D("len: %u, retry %u", len, loop);
+       ret = fn(session->outbuf + len, IPSET_OUTBUFLEN - len,
                 session->data, opt, session->envopts);
        
        if (ret < 0)
                return ipset_err(session,
                        "Internal error at printing to output buffer");
 
-       if (ret >= len) {
+       if (ret >= IPSET_OUTBUFLEN - len) {
                /* Buffer was too small, push it out and retry */
+               D("print buffer and try again: %u", len);
                if (loop++)
                        return ipset_err(session,
                        "Internal error at printing, loop detected!");
 
-               session->outbuf[IPSET_OUTBUFLEN - len] = '\0';
+               session->outbuf[len] = '\0';
                if (!call_outfn(session))
                        goto retry;
        }