Eliminate a number of instances of undefined behavior related to
passing NULL in parameters having "nonnull" annotations.

Found with gcc's undefined behavior sanitizer.

Signed-off-by: Lance Richardson <lrich...@redhat.com>
---
 lib/netlink.c             |  5 ++++-
 lib/ofpbuf.c              |  2 +-
 lib/svec.c                |  4 +++-
 lib/util.c                |  2 +-
 lib/util.h                | 21 +++++++++++++++++++++
 ovn/utilities/ovn-nbctl.c | 18 ++++++++++--------
 6 files changed, 40 insertions(+), 12 deletions(-)

diff --git a/lib/netlink.c b/lib/netlink.c
index 3da22a1..0246131 100644
--- a/lib/netlink.c
+++ b/lib/netlink.c
@@ -241,7 +241,10 @@ void
 nl_msg_put_unspec(struct ofpbuf *msg, uint16_t type,
                   const void *data, size_t size)
 {
-    memcpy(nl_msg_put_unspec_uninit(msg, type, size), data, size);
+    void *ptr;
+
+    ptr = nl_msg_put_unspec_uninit(msg, type, size);
+    nullable_memcpy(ptr, data, size);
 }
 
 /* Appends a Netlink attribute of the given 'type' and no payload to 'msg'.
diff --git a/lib/ofpbuf.c b/lib/ofpbuf.c
index 3019c4a..f4a9040 100644
--- a/lib/ofpbuf.c
+++ b/lib/ofpbuf.c
@@ -375,7 +375,7 @@ void *
 ofpbuf_put_zeros(struct ofpbuf *b, size_t size)
 {
     void *dst = ofpbuf_put_uninit(b, size);
-    memset(dst, 0, size);
+    nullable_memset(dst, 0, size);
     return dst;
 }
 
diff --git a/lib/svec.c b/lib/svec.c
index aad04e3..297a60c 100644
--- a/lib/svec.c
+++ b/lib/svec.c
@@ -127,7 +127,9 @@ compare_strings(const void *a_, const void *b_)
 void
 svec_sort(struct svec *svec)
 {
-    qsort(svec->names, svec->n, sizeof *svec->names, compare_strings);
+    if (svec->n) {
+        qsort(svec->names, svec->n, sizeof *svec->names, compare_strings);
+    }
 }
 
 void
diff --git a/lib/util.c b/lib/util.c
index b2a1f8a..85b9350 100644
--- a/lib/util.c
+++ b/lib/util.c
@@ -132,7 +132,7 @@ void *
 xmemdup(const void *p_, size_t size)
 {
     void *p = xmalloc(size);
-    memcpy(p, p_, size);
+    nullable_memcpy(p, p_, size);
     return p;
 }
 
diff --git a/lib/util.h b/lib/util.h
index d2374b2..c2d1c3f 100644
--- a/lib/util.h
+++ b/lib/util.h
@@ -135,6 +135,27 @@ void free_cacheline(void *);
 void ovs_strlcpy(char *dst, const char *src, size_t size);
 void ovs_strzcpy(char *dst, const char *src, size_t size);
 
+/* The C standards say that neither the 'dst' nor 'src' argument to
+ * memcpy() may be null, even if 'n' is zero.  This wrapper tolerates
+ * the null case. */
+static inline void
+nullable_memcpy(void *dst, const void *src, size_t n)
+{
+    if (n) {
+        memcpy(dst, src, n);
+    }
+}
+
+/* The C standards say that the 'dst' argument to memset may not be
+ * null, even if 'n' is zero.  This wrapper tolerates the null case. */
+static inline void
+nullable_memset(void *dst, int c, size_t n)
+{
+    if (n) {
+        memset(dst, c, n);
+    }
+}
+
 /* Copy string SRC to DST, but no more bytes than the shorter of DST or SRC.
  * DST and SRC must both be char arrays, not pointers, and with GNU C, this
  * raises a compiler error if either DST or SRC is a pointer instead of an
diff --git a/ovn/utilities/ovn-nbctl.c b/ovn/utilities/ovn-nbctl.c
index bd0160a..bea010a 100644
--- a/ovn/utilities/ovn-nbctl.c
+++ b/ovn/utilities/ovn-nbctl.c
@@ -920,7 +920,7 @@ nbctl_lsp_add(struct ctl_context *ctx)
     nbrec_logical_switch_verify_ports(ls);
     struct nbrec_logical_switch_port **new_ports = xmalloc(sizeof *new_ports *
                                                     (ls->n_ports + 1));
-    memcpy(new_ports, ls->ports, sizeof *new_ports * ls->n_ports);
+    nullable_memcpy(new_ports, ls->ports, sizeof *new_ports * ls->n_ports);
     new_ports[ls->n_ports] = CONST_CAST(struct nbrec_logical_switch_port *,
                                              lsp);
     nbrec_logical_switch_set_ports(ls, new_ports, ls->n_ports + 1);
@@ -1379,7 +1379,7 @@ nbctl_acl_add(struct ctl_context *ctx)
     /* Insert the acl into the logical switch. */
     nbrec_logical_switch_verify_acls(ls);
     struct nbrec_acl **new_acls = xmalloc(sizeof *new_acls * (ls->n_acls + 1));
-    memcpy(new_acls, ls->acls, sizeof *new_acls * ls->n_acls);
+    nullable_memcpy(new_acls, ls->acls, sizeof *new_acls * ls->n_acls);
     new_acls[ls->n_acls] = acl;
     nbrec_logical_switch_set_acls(ls, new_acls, ls->n_acls + 1);
     free(new_acls);
@@ -1697,7 +1697,8 @@ nbctl_lr_lb_add(struct ctl_context *ctx)
     struct nbrec_load_balancer **new_lbs
         = xmalloc(sizeof *new_lbs * (lr->n_load_balancer + 1));
 
-    memcpy(new_lbs, lr->load_balancer, sizeof *new_lbs * lr->n_load_balancer);
+    nullable_memcpy(new_lbs, lr->load_balancer,
+                    sizeof *new_lbs * lr->n_load_balancer);
     new_lbs[lr->n_load_balancer] = CONST_CAST(struct nbrec_load_balancer *,
             new_lb);
     nbrec_logical_router_set_load_balancer(lr, new_lbs,
@@ -1793,7 +1794,8 @@ nbctl_ls_lb_add(struct ctl_context *ctx)
     struct nbrec_load_balancer **new_lbs
         = xmalloc(sizeof *new_lbs * (ls->n_load_balancer + 1));
 
-    memcpy(new_lbs, ls->load_balancer, sizeof *new_lbs * ls->n_load_balancer);
+    nullable_memcpy(new_lbs, ls->load_balancer,
+                    sizeof *new_lbs * ls->n_load_balancer);
     new_lbs[ls->n_load_balancer] = CONST_CAST(struct nbrec_load_balancer *,
             new_lb);
     nbrec_logical_switch_set_load_balancer(ls, new_lbs,
@@ -2200,8 +2202,8 @@ nbctl_lr_route_add(struct ctl_context *ctx)
     nbrec_logical_router_verify_static_routes(lr);
     struct nbrec_logical_router_static_route **new_routes
         = xmalloc(sizeof *new_routes * (lr->n_static_routes + 1));
-    memcpy(new_routes, lr->static_routes,
-           sizeof *new_routes * lr->n_static_routes);
+    nullable_memcpy(new_routes, lr->static_routes,
+               sizeof *new_routes * lr->n_static_routes);
     new_routes[lr->n_static_routes] = route;
     nbrec_logical_router_set_static_routes(lr, new_routes,
                                            lr->n_static_routes + 1);
@@ -2364,7 +2366,7 @@ nbctl_lr_nat_add(struct ctl_context *ctx)
     /* Insert the NAT into the logical router. */
     nbrec_logical_router_verify_nat(lr);
     struct nbrec_nat **new_nats = xmalloc(sizeof *new_nats * (lr->n_nat + 1));
-    memcpy(new_nats, lr->nat, sizeof *new_nats * lr->n_nat);
+    nullable_memcpy(new_nats, lr->nat, sizeof *new_nats * lr->n_nat);
     new_nats[lr->n_nat] = nat;
     nbrec_logical_router_set_nat(lr, new_nats, lr->n_nat + 1);
     free(new_nats);
@@ -2642,7 +2644,7 @@ nbctl_lrp_add(struct ctl_context *ctx)
     nbrec_logical_router_verify_ports(lr);
     struct nbrec_logical_router_port **new_ports = xmalloc(sizeof *new_ports *
                                                         (lr->n_ports + 1));
-    memcpy(new_ports, lr->ports, sizeof *new_ports * lr->n_ports);
+    nullable_memcpy(new_ports, lr->ports, sizeof *new_ports * lr->n_ports);
     new_ports[lr->n_ports] = CONST_CAST(struct nbrec_logical_router_port *,
                                              lrp);
     nbrec_logical_router_set_ports(lr, new_ports, lr->n_ports + 1);
-- 
2.9.4

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to