]> git.ipfire.org Git - thirdparty/ipset.git/commitdiff
Handle internal printing errors
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Thu, 23 Dec 2010 14:28:28 +0000 (15:28 +0100)
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Thu, 23 Dec 2010 14:28:28 +0000 (15:28 +0100)
Internal printing errors were not reported, handle them by setjmp/longjmp.

lib/session.c

index 2a57378a15077a8d0fa35bd62d17039e476c9d12..311e5df40216c2d2b855709ed37029d17ac07c53 100644 (file)
@@ -6,6 +6,7 @@
  */
 #include <assert.h>                            /* assert */
 #include <errno.h>                             /* errno */
+#include <setjmp.h>                            /* setjmp, longjmp */
 #include <stdio.h>                             /* snprintf */
 #include <stdarg.h>                            /* va_* */
 #include <stdlib.h>                            /* free */
@@ -629,6 +630,9 @@ call_outfn(struct ipset_session *session)
        return ret < 0 ? ret : 0;
 }
 
+/* Handle printing failures */
+static jmp_buf printf_failure;
+
 static int __attribute__((format(printf,2,3)))
 safe_snprintf(struct ipset_session *session, const char *fmt, ...)
 {
@@ -643,16 +647,20 @@ retry:
                        fmt, args);
        va_end(args);
        
-       if (ret < 0)
-               return ipset_err(session,
-                                "Internal error at printing to output buffer");
+       if (ret < 0) {
+               ipset_err(session,
+                        "Internal error at printing to output buffer");
+               longjmp(printf_failure, 1);
+       }
 
        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,
+               if (loop++) {
+                       ipset_err(session,
                                "Internal error at printing, loop detected!");
+                       longjmp(printf_failure, 1);
+               }
 
                session->outbuf[len] = '\0';
                if (!call_outfn(session))
@@ -673,16 +681,20 @@ retry:
        ret = fn(session->outbuf + len, IPSET_OUTBUFLEN - len,
                 session->data, opt, session->envopts);
        
-       if (ret < 0)
-               return ipset_err(session,
+       if (ret < 0) {
+               ipset_err(session,
                        "Internal error at printing to output buffer");
+               longjmp(printf_failure, 1);
+       }
 
        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!");
+               if (loop++) {
+                       ipset_err(session,
+                               "Internal error at printing, loop detected!");
+                       longjmp(printf_failure, 1);
+               }
 
                session->outbuf[len] = '\0';
                if (!call_outfn(session))
@@ -904,6 +916,9 @@ callback_list(struct ipset_session *session, struct nlattr *nla[],
 {
        struct ipset_data *data = session->data;
 
+       if (setjmp(printf_failure))
+               return MNL_CB_ERROR;
+
        if (!nla[IPSET_ATTR_SETNAME])
                FAILURE("Broken %s kernel message: missing setname!",
                        cmd2name[cmd]);