On 16 Mar 2023, at 17:36, James Raphael Tiovalen wrote:

> This commit addresses several high and medium-impact Coverity defects by
> fixing several possible null-pointer dereferences and potentially
> uninitialized variables.
>
> There were cases when crashes were encountered when some null pointers
> were dereferenced. Null pointer checks and alternative code paths have
> been added to prevent unwanted crashes. Additionally, some struct
> variables were not initialized. Zero-initializations have been added to
> prevent potential data leaks or undefined behavior.
>
> Some variables would always be initialized by either the code flow or
> the compiler and some pointers would never be null. Thus, some Coverity
> reports might be false positives. That said, it is still considered best
> practice to perform null pointer checks and initialize variables upfront
> just in case to ensure the overall resilience and security of OVS, as
> long as they do not impact performance-critical code. As a bonus, it
> would also make static analyzer tools, such as Coverity, happy.
>
> Unit tests have been successfully executed via `make check` and they
> successfully passed.

I did not review this, but I noticed you do null checks for memset() and 
memcpy(). But there are functions for this in OVS like nullable_memset() and 
nullable_memcpy(), maybe some of the changes might benefit from using this.

In addition, there is also a nullable_string_is_equal() which might be useful 
in some cases.

//Eelco

> Signed-off-by: James Raphael Tiovalen <[email protected]>
> ---
> v5:
> Improve commit message to better describe the intent of this patch.
>
> v4:
> - Fix some apply-robot checkpatch errors and warnings.
> - Fix github-robot build failure: linux clang test asan.
>
> v3:
> Fix some apply-robot checkpatch errors and warnings.
>
> v2:
> Fix some apply-robot checkpatch errors and warnings.
> ---
>  lib/dp-packet.c         |  69 ++++++++++++------
>  lib/dpctl.c             |  66 +++++++++--------
>  lib/json.c              |  32 +++++---
>  lib/latch-unix.c        |   2 +-
>  lib/memory.c            |  10 ++-
>  lib/netdev-native-tnl.c |  48 +++++++-----
>  lib/odp-execute.c       |  91 ++++++++++++-----------
>  lib/pcap-file.c         |   5 +-
>  lib/rtnetlink.c         |  11 ++-
>  lib/sflow_agent.c       |  91 +++++++++++++++--------
>  lib/shash.c             |   4 +-
>  lib/sset.c              |   7 +-
>  ovsdb/condition.c       |  10 ++-
>  ovsdb/file.c            |  26 +++++--
>  ovsdb/jsonrpc-server.c  |   5 +-
>  ovsdb/monitor.c         |  49 ++++++++++---
>  ovsdb/ovsdb-client.c    |  45 ++++++++----
>  ovsdb/ovsdb-server.c    |  15 ++--
>  ovsdb/ovsdb-util.c      |   9 +++
>  ovsdb/ovsdb.c           | 124 ++++++++++++++++---------------
>  ovsdb/query.c           |   4 +-
>  ovsdb/replication.c     |  14 ++--
>  ovsdb/row.c             |   4 +-
>  ovsdb/table.c           |   2 +-
>  ovsdb/transaction.c     |   8 +-
>  utilities/ovs-vsctl.c   | 157 ++++++++++++++++++++++++----------------
>  vtep/vtep-ctl.c         |  79 +++++++++++---------
>  27 files changed, 607 insertions(+), 380 deletions(-)
>
> diff --git a/lib/dp-packet.c b/lib/dp-packet.c
> index ae8ab5800..50cb30681 100644
> --- a/lib/dp-packet.c
> +++ b/lib/dp-packet.c
> @@ -171,7 +171,11 @@ dp_packet_new_with_headroom(size_t size, size_t headroom)
>  struct dp_packet *
>  dp_packet_clone(const struct dp_packet *buffer)
>  {
> -    return dp_packet_clone_with_headroom(buffer, 0);
> +    if (buffer) {
> +        return dp_packet_clone_with_headroom(buffer, 0);
> +    } else {
> +        return NULL;
> +    }
>  }
>
>  /* Creates and returns a new dp_packet whose data are copied from 'buffer'.
> @@ -183,26 +187,32 @@ dp_packet_clone_with_headroom(const struct dp_packet 
> *buffer, size_t headroom)
>      struct dp_packet *new_buffer;
>      uint32_t mark;
>
> -    new_buffer = dp_packet_clone_data_with_headroom(dp_packet_data(buffer),
> -                                                 dp_packet_size(buffer),
> -                                                 headroom);
> -    /* Copy the following fields into the returned buffer: l2_pad_size,
> -     * l2_5_ofs, l3_ofs, l4_ofs, cutlen, packet_type and md. */
> -    memcpy(&new_buffer->l2_pad_size, &buffer->l2_pad_size,
> -            sizeof(struct dp_packet) -
> -            offsetof(struct dp_packet, l2_pad_size));
> +    const void *data_dp = dp_packet_data(buffer);
>
> -    *dp_packet_ol_flags_ptr(new_buffer) = *dp_packet_ol_flags_ptr(buffer);
> -    *dp_packet_ol_flags_ptr(new_buffer) &= DP_PACKET_OL_SUPPORTED_MASK;
> +    if (data_dp) {
> +        new_buffer = dp_packet_clone_data_with_headroom(data_dp,
> +                                                        
> dp_packet_size(buffer),
> +                                                        headroom);
> +        /* Copy the following fields into the returned buffer: l2_pad_size,
> +        * l2_5_ofs, l3_ofs, l4_ofs, cutlen, packet_type and md. */
> +        memcpy(&new_buffer->l2_pad_size, &buffer->l2_pad_size,
> +                sizeof(struct dp_packet) -
> +                offsetof(struct dp_packet, l2_pad_size));
>
> -    if (dp_packet_rss_valid(buffer)) {
> -        dp_packet_set_rss_hash(new_buffer, dp_packet_get_rss_hash(buffer));
> -    }
> -    if (dp_packet_has_flow_mark(buffer, &mark)) {
> -        dp_packet_set_flow_mark(new_buffer, mark);
> -    }
> +        *dp_packet_ol_flags_ptr(new_buffer) = 
> *dp_packet_ol_flags_ptr(buffer);
> +        *dp_packet_ol_flags_ptr(new_buffer) &= DP_PACKET_OL_SUPPORTED_MASK;
> +
> +        if (dp_packet_rss_valid(buffer)) {
> +            dp_packet_set_rss_hash(new_buffer, 
> dp_packet_get_rss_hash(buffer));
> +        }
> +        if (dp_packet_has_flow_mark(buffer, &mark)) {
> +            dp_packet_set_flow_mark(new_buffer, mark);
> +        }
>
> -    return new_buffer;
> +        return new_buffer;
> +    } else {
> +        return NULL;
> +    }
>  }
>
>  /* Creates and returns a new dp_packet that initially contains a copy of the
> @@ -323,8 +333,11 @@ dp_packet_shift(struct dp_packet *b, int delta)
>
>      if (delta != 0) {
>          char *dst = (char *) dp_packet_data(b) + delta;
> -        memmove(dst, dp_packet_data(b), dp_packet_size(b));
> -        dp_packet_set_data(b, dst);
> +        const void *data_dp = dp_packet_data(b);
> +        if (data_dp) {
> +            memmove(dst, data_dp, dp_packet_size(b));
> +            dp_packet_set_data(b, dst);
> +        }
>      }
>  }
>
> @@ -348,7 +361,9 @@ void *
>  dp_packet_put_zeros(struct dp_packet *b, size_t size)
>  {
>      void *dst = dp_packet_put_uninit(b, size);
> -    memset(dst, 0, size);
> +    if (dst) {
> +        memset(dst, 0, size);
> +    }
>      return dst;
>  }
>
> @@ -359,7 +374,9 @@ void *
>  dp_packet_put(struct dp_packet *b, const void *p, size_t size)
>  {
>      void *dst = dp_packet_put_uninit(b, size);
> -    memcpy(dst, p, size);
> +    if (dst) {
> +        memcpy(dst, p, size);
> +    }
>      return dst;
>  }
>
> @@ -431,7 +448,9 @@ void *
>  dp_packet_push_zeros(struct dp_packet *b, size_t size)
>  {
>      void *dst = dp_packet_push_uninit(b, size);
> -    memset(dst, 0, size);
> +    if (dst) {
> +        memset(dst, 0, size);
> +    }
>      return dst;
>  }
>
> @@ -442,7 +461,9 @@ void *
>  dp_packet_push(struct dp_packet *b, const void *p, size_t size)
>  {
>      void *dst = dp_packet_push_uninit(b, size);
> -    memcpy(dst, p, size);
> +    if (dst) {
> +        memcpy(dst, p, size);
> +    }
>      return dst;
>  }
>
> diff --git a/lib/dpctl.c b/lib/dpctl.c
> index c501a0cd7..6472990cc 100644
> --- a/lib/dpctl.c
> +++ b/lib/dpctl.c
> @@ -336,12 +336,14 @@ dpctl_add_if(int argc OVS_UNUSED, const char *argv[],
>                  value = "";
>              }
>
> -            if (!strcmp(key, "type")) {
> -                type = value;
> -            } else if (!strcmp(key, "port_no")) {
> -                port_no = u32_to_odp(atoi(value));
> -            } else if (!smap_add_once(&args, key, value)) {
> -                dpctl_error(dpctl_p, 0, "duplicate \"%s\" option", key);
> +            if (key) {
> +                if (!strcmp(key, "type")) {
> +                    type = value;
> +                } else if (!strcmp(key, "port_no")) {
> +                    port_no = u32_to_odp(atoi(value));
> +                } else if (!smap_add_once(&args, key, value)) {
> +                    dpctl_error(dpctl_p, 0, "duplicate \"%s\" option", key);
> +                }
>              }
>          }
>
> @@ -454,25 +456,29 @@ dpctl_set_if(int argc, const char *argv[], struct 
> dpctl_params *dpctl_p)
>                  value = "";
>              }
>
> -            if (!strcmp(key, "type")) {
> -                if (strcmp(value, type)) {
> -                    dpctl_error(dpctl_p, 0,
> -                                "%s: can't change type from %s to %s",
> -                                 name, type, value);
> -                    error = EINVAL;
> -                    goto next_destroy_args;
> -                }
> -            } else if (!strcmp(key, "port_no")) {
> -                if (port_no != u32_to_odp(atoi(value))) {
> -                    dpctl_error(dpctl_p, 0, "%s: can't change port number 
> from"
> -                              " %"PRIu32" to %d", name, port_no, 
> atoi(value));
> -                    error = EINVAL;
> -                    goto next_destroy_args;
> +            if (key) {
> +                if (!strcmp(key, "type")) {
> +                    if (strcmp(value, type)) {
> +                        dpctl_error(dpctl_p, 0,
> +                                    "%s: can't change type from %s to %s",
> +                                    name, type, value);
> +                        error = EINVAL;
> +                        goto next_destroy_args;
> +                    }
> +                } else if (!strcmp(key, "port_no")) {
> +                    if (port_no != u32_to_odp(atoi(value))) {
> +                        dpctl_error(dpctl_p, 0,
> +                                    "%s: can't change port number from"
> +                                    " %"PRIu32" to %d", name, port_no,
> +                                    atoi(value));
> +                        error = EINVAL;
> +                        goto next_destroy_args;
> +                    }
> +                } else if (value[0] == '\0') {
> +                    smap_remove(&args, key);
> +                } else {
> +                    smap_replace(&args, key, value);
>                  }
> -            } else if (value[0] == '\0') {
> -                smap_remove(&args, key);
> -            } else {
> -                smap_replace(&args, key, value);
>              }
>          }
>
> @@ -693,12 +699,14 @@ show_dpif(struct dpif *dpif, struct dpctl_params 
> *dpctl_p)
>                  error = netdev_get_config(netdev, &config);
>                  if (!error) {
>                      const struct smap_node **nodes = smap_sort(&config);
> -                    for (size_t j = 0; j < smap_count(&config); j++) {
> -                        const struct smap_node *node = nodes[j];
> -                        dpctl_print(dpctl_p, "%c %s=%s", j ? ',' : ':',
> -                                    node->key, node->value);
> +                    if (nodes) {
> +                        for (size_t j = 0; j < smap_count(&config); j++) {
> +                            const struct smap_node *node = nodes[j];
> +                            dpctl_print(dpctl_p, "%c %s=%s", j ? ',' : ':',
> +                                        node->key, node->value);
> +                        }
> +                        free(nodes);
>                      }
> -                    free(nodes);
>                  } else {
>                      dpctl_print(dpctl_p, ", could not retrieve configuration 
> "
>                                           "(%s)",  ovs_strerror(error));
> diff --git a/lib/json.c b/lib/json.c
> index aded8bb01..09683b54f 100644
> --- a/lib/json.c
> +++ b/lib/json.c
> @@ -342,8 +342,12 @@ json_object(const struct json *json)
>  bool
>  json_boolean(const struct json *json)
>  {
> -    ovs_assert(json->type == JSON_TRUE || json->type == JSON_FALSE);
> -    return json->type == JSON_TRUE;
> +    if (json) {
> +        ovs_assert(json->type == JSON_TRUE || json->type == JSON_FALSE);
> +        return json->type == JSON_TRUE;
> +    } else {
> +        return false;
> +    }
>  }
>
>  double
> @@ -497,13 +501,15 @@ json_hash_object(const struct shash *object, size_t 
> basis)
>      size_t n, i;
>
>      nodes = shash_sort(object);
> -    n = shash_count(object);
> -    for (i = 0; i < n; i++) {
> -        const struct shash_node *node = nodes[i];
> -        basis = hash_string(node->name, basis);
> -        basis = json_hash(node->data, basis);
> +    if (nodes) {
> +        n = shash_count(object);
> +        for (i = 0; i < n; i++) {
> +            const struct shash_node *node = nodes[i];
> +            basis = hash_string(node->name, basis);
> +            basis = json_hash(node->data, basis);
> +        }
> +        free(nodes);
>      }
> -    free(nodes);
>      return basis;
>  }
>
> @@ -1654,11 +1660,13 @@ json_serialize_object(const struct shash *object, 
> struct json_serializer *s)
>          size_t n, i;
>
>          nodes = shash_sort(object);
> -        n = shash_count(object);
> -        for (i = 0; i < n; i++) {
> -            json_serialize_object_member(i, nodes[i], s);
> +        if (nodes) {
> +            n = shash_count(object);
> +            for (i = 0; i < n; i++) {
> +                json_serialize_object_member(i, nodes[i], s);
> +            }
> +            free(nodes);
>          }
> -        free(nodes);
>      } else {
>          struct shash_node *node;
>          size_t i;
> diff --git a/lib/latch-unix.c b/lib/latch-unix.c
> index f4d10c39a..262f111e4 100644
> --- a/lib/latch-unix.c
> +++ b/lib/latch-unix.c
> @@ -71,7 +71,7 @@ latch_set(struct latch *latch)
>  bool
>  latch_is_set(const struct latch *latch)
>  {
> -    struct pollfd pfd;
> +    struct pollfd pfd = {0, 0, 0};
>      int retval;
>
>      pfd.fd = latch->fds[0];
> diff --git a/lib/memory.c b/lib/memory.c
> index da97476c6..5ece04807 100644
> --- a/lib/memory.c
> +++ b/lib/memory.c
> @@ -116,13 +116,15 @@ compose_report(const struct simap *usage, struct ds *s)
>      size_t n = simap_count(usage);
>      size_t i;
>
> -    for (i = 0; i < n; i++) {
> -        const struct simap_node *node = nodes[i];
> +    if (nodes) {
> +        for (i = 0; i < n; i++) {
> +            const struct simap_node *node = nodes[i];
>
> -        ds_put_format(s, "%s:%u ", node->name, node->data);
> +            ds_put_format(s, "%s:%u ", node->name, node->data);
> +        }
> +        free(nodes);
>      }
>      ds_chomp(s, ' ');
> -    free(nodes);
>  }
>
>  /* Logs the contents of 'usage', as a collection of name-count pairs.
> diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c
> index b89dfdd52..e2dd61880 100644
> --- a/lib/netdev-native-tnl.c
> +++ b/lib/netdev-native-tnl.c
> @@ -221,16 +221,20 @@ netdev_tnl_calc_udp_csum(struct udp_header *udp, struct 
> dp_packet *packet,
>  {
>      uint32_t csum;
>
> -    if (netdev_tnl_is_header_ipv6(dp_packet_data(packet))) {
> -        csum = packet_csum_pseudoheader6(netdev_tnl_ipv6_hdr(
> -                                         dp_packet_data(packet)));
> -    } else {
> -        csum = packet_csum_pseudoheader(netdev_tnl_ip_hdr(
> -                                        dp_packet_data(packet)));
> -    }
> +    void *data_dp = dp_packet_data(packet);
> +
> +    if (data_dp) {
> +        if (netdev_tnl_is_header_ipv6(data_dp)) {
> +            csum = packet_csum_pseudoheader6(netdev_tnl_ipv6_hdr(
> +                                             data_dp));
> +        } else {
> +            csum = packet_csum_pseudoheader(netdev_tnl_ip_hdr(
> +                                            data_dp));
> +        }
>
> -    csum = csum_continue(csum, udp, ip_tot_size);
> -    udp->udp_csum = csum_finish(csum);
> +        csum = csum_continue(csum, udp, ip_tot_size);
> +        udp->udp_csum = csum_finish(csum);
> +    }
>
>      if (!udp->udp_csum) {
>          udp->udp_csum = htons(0xffff);
> @@ -425,20 +429,24 @@ netdev_gre_pop_header(struct dp_packet *packet)
>      struct flow_tnl *tnl = &md->tunnel;
>      int hlen = sizeof(struct eth_header) + 4;
>
> -    hlen += netdev_tnl_is_header_ipv6(dp_packet_data(packet)) ?
> -            IPV6_HEADER_LEN : IP_HEADER_LEN;
> +    const void *data_dp = dp_packet_data(packet);
>
> -    pkt_metadata_init_tnl(md);
> -    if (hlen > dp_packet_size(packet)) {
> -        goto err;
> -    }
> +    if (data_dp) {
> +        hlen += netdev_tnl_is_header_ipv6(data_dp) ?
> +                IPV6_HEADER_LEN : IP_HEADER_LEN;
>
> -    hlen = parse_gre_header(packet, tnl);
> -    if (hlen < 0) {
> -        goto err;
> -    }
> +        pkt_metadata_init_tnl(md);
> +        if (hlen > dp_packet_size(packet)) {
> +            goto err;
> +        }
>
> -    dp_packet_reset_packet(packet, hlen);
> +        hlen = parse_gre_header(packet, tnl);
> +        if (hlen < 0) {
> +            goto err;
> +        }
> +
> +        dp_packet_reset_packet(packet, hlen);
> +    }
>
>      return packet;
>  err:
> diff --git a/lib/odp-execute.c b/lib/odp-execute.c
> index 5cf6fbec0..b8cf3db55 100644
> --- a/lib/odp-execute.c
> +++ b/lib/odp-execute.c
> @@ -147,42 +147,45 @@ odp_set_ipv4(struct dp_packet *packet, const struct 
> ovs_key_ipv4 *key,
>      uint8_t new_tos;
>      uint8_t new_ttl;
>
> -    if (mask->ipv4_src) {
> -        ip_src_nh = get_16aligned_be32(&nh->ip_src);
> -        new_ip_src = key->ipv4_src | (ip_src_nh & ~mask->ipv4_src);
> +    if (nh) {
> +        if (mask->ipv4_src) {
> +            ip_src_nh = get_16aligned_be32(&nh->ip_src);
> +            new_ip_src = key->ipv4_src | (ip_src_nh & ~mask->ipv4_src);
>
> -        if (ip_src_nh != new_ip_src) {
> -            packet_set_ipv4_addr(packet, &nh->ip_src, new_ip_src);
> +            if (ip_src_nh != new_ip_src) {
> +                packet_set_ipv4_addr(packet, &nh->ip_src, new_ip_src);
> +            }
>          }
> -    }
>
> -    if (mask->ipv4_dst) {
> -        ip_dst_nh = get_16aligned_be32(&nh->ip_dst);
> -        new_ip_dst = key->ipv4_dst | (ip_dst_nh & ~mask->ipv4_dst);
> +        if (mask->ipv4_dst) {
> +            ip_dst_nh = get_16aligned_be32(&nh->ip_dst);
> +            new_ip_dst = key->ipv4_dst | (ip_dst_nh & ~mask->ipv4_dst);
>
> -        if (ip_dst_nh != new_ip_dst) {
> -            packet_set_ipv4_addr(packet, &nh->ip_dst, new_ip_dst);
> +            if (ip_dst_nh != new_ip_dst) {
> +                packet_set_ipv4_addr(packet, &nh->ip_dst, new_ip_dst);
> +            }
>          }
> -    }
>
> -    if (mask->ipv4_tos) {
> -        new_tos = key->ipv4_tos | (nh->ip_tos & ~mask->ipv4_tos);
> +        if (mask->ipv4_tos) {
> +            new_tos = key->ipv4_tos | (nh->ip_tos & ~mask->ipv4_tos);
>
> -        if (nh->ip_tos != new_tos) {
> -            nh->ip_csum = recalc_csum16(nh->ip_csum,
> -                                        htons((uint16_t) nh->ip_tos),
> -                                        htons((uint16_t) new_tos));
> -            nh->ip_tos = new_tos;
> +            if (nh->ip_tos != new_tos) {
> +                nh->ip_csum = recalc_csum16(nh->ip_csum,
> +                                            htons((uint16_t) nh->ip_tos),
> +                                            htons((uint16_t) new_tos));
> +                nh->ip_tos = new_tos;
> +            }
>          }
> -    }
>
> -    if (OVS_LIKELY(mask->ipv4_ttl)) {
> -        new_ttl = key->ipv4_ttl | (nh->ip_ttl & ~mask->ipv4_ttl);
> +        if (OVS_LIKELY(mask->ipv4_ttl)) {
> +            new_ttl = key->ipv4_ttl | (nh->ip_ttl & ~mask->ipv4_ttl);
>
> -        if (OVS_LIKELY(nh->ip_ttl != new_ttl)) {
> -            nh->ip_csum = recalc_csum16(nh->ip_csum, htons(nh->ip_ttl << 8),
> -                                        htons(new_ttl << 8));
> -            nh->ip_ttl = new_ttl;
> +            if (OVS_LIKELY(nh->ip_ttl != new_ttl)) {
> +                nh->ip_csum = recalc_csum16(nh->ip_csum,
> +                                            htons(nh->ip_ttl << 8),
> +                                            htons(new_ttl << 8));
> +                nh->ip_ttl = new_ttl;
> +            }
>          }
>      }
>  }
> @@ -276,23 +279,25 @@ set_arp(struct dp_packet *packet, const struct 
> ovs_key_arp *key,
>  {
>      struct arp_eth_header *arp = dp_packet_l3(packet);
>
> -    if (!mask) {
> -        arp->ar_op = key->arp_op;
> -        arp->ar_sha = key->arp_sha;
> -        put_16aligned_be32(&arp->ar_spa, key->arp_sip);
> -        arp->ar_tha = key->arp_tha;
> -        put_16aligned_be32(&arp->ar_tpa, key->arp_tip);
> -    } else {
> -        ovs_be32 ar_spa = get_16aligned_be32(&arp->ar_spa);
> -        ovs_be32 ar_tpa = get_16aligned_be32(&arp->ar_tpa);
> -
> -        arp->ar_op = key->arp_op | (arp->ar_op & ~mask->arp_op);
> -        ether_addr_copy_masked(&arp->ar_sha, key->arp_sha, mask->arp_sha);
> -        put_16aligned_be32(&arp->ar_spa,
> -                           key->arp_sip | (ar_spa & ~mask->arp_sip));
> -        ether_addr_copy_masked(&arp->ar_tha, key->arp_tha, mask->arp_tha);
> -        put_16aligned_be32(&arp->ar_tpa,
> -                           key->arp_tip | (ar_tpa & ~mask->arp_tip));
> +    if (arp) {
> +        if (!mask) {
> +            arp->ar_op = key->arp_op;
> +            arp->ar_sha = key->arp_sha;
> +            put_16aligned_be32(&arp->ar_spa, key->arp_sip);
> +            arp->ar_tha = key->arp_tha;
> +            put_16aligned_be32(&arp->ar_tpa, key->arp_tip);
> +        } else {
> +            ovs_be32 ar_spa = get_16aligned_be32(&arp->ar_spa);
> +            ovs_be32 ar_tpa = get_16aligned_be32(&arp->ar_tpa);
> +
> +            arp->ar_op = key->arp_op | (arp->ar_op & ~mask->arp_op);
> +            ether_addr_copy_masked(&arp->ar_sha, key->arp_sha, 
> mask->arp_sha);
> +            put_16aligned_be32(&arp->ar_spa,
> +                            key->arp_sip | (ar_spa & ~mask->arp_sip));
> +            ether_addr_copy_masked(&arp->ar_tha, key->arp_tha, 
> mask->arp_tha);
> +            put_16aligned_be32(&arp->ar_tpa,
> +                            key->arp_tip | (ar_tpa & ~mask->arp_tip));
> +        }
>      }
>  }
>
> diff --git a/lib/pcap-file.c b/lib/pcap-file.c
> index 3ed7ea488..7cb6f5b2a 100644
> --- a/lib/pcap-file.c
> +++ b/lib/pcap-file.c
> @@ -291,7 +291,10 @@ ovs_pcap_write(struct pcap_file *p_file, struct 
> dp_packet *buf)
>      prh.incl_len = dp_packet_size(buf);
>      prh.orig_len = dp_packet_size(buf);
>      ignore(fwrite(&prh, sizeof prh, 1, p_file->file));
> -    ignore(fwrite(dp_packet_data(buf), dp_packet_size(buf), 1, 
> p_file->file));
> +    const void *data_dp = dp_packet_data(buf);
> +    if (data_dp) {
> +        ignore(fwrite(data_dp, dp_packet_size(buf), 1, p_file->file));
> +    }
>      fflush(p_file->file);
>  }
>
> diff --git a/lib/rtnetlink.c b/lib/rtnetlink.c
> index f67352603..67a0134ed 100644
> --- a/lib/rtnetlink.c
> +++ b/lib/rtnetlink.c
> @@ -131,10 +131,13 @@ rtnetlink_parse(struct ofpbuf *buf, struct 
> rtnetlink_change *change)
>                  change->irrelevant = true;
>              }
>
> +            if (ifinfo) {
> +                change->if_index   = ifinfo->ifi_index;
> +                change->ifi_flags  = ifinfo->ifi_flags;
> +            }
> +
>              change->nlmsg_type     = nlmsg->nlmsg_type;
> -            change->if_index       = ifinfo->ifi_index;
>              change->ifname         = nl_attr_get_string(attrs[IFLA_IFNAME]);
> -            change->ifi_flags      = ifinfo->ifi_flags;
>              change->master_ifindex = (attrs[IFLA_MASTER]
>                                        ? nl_attr_get_u32(attrs[IFLA_MASTER])
>                                        : 0);
> @@ -178,7 +181,9 @@ rtnetlink_parse(struct ofpbuf *buf, struct 
> rtnetlink_change *change)
>              ifaddr = ofpbuf_at(buf, NLMSG_HDRLEN, sizeof *ifaddr);
>
>              change->nlmsg_type     = nlmsg->nlmsg_type;
> -            change->if_index       = ifaddr->ifa_index;
> +            if (ifaddr) {
> +                change->if_index   = ifaddr->ifa_index;
> +            }
>              change->ifname         = (attrs[IFA_LABEL]
>                                        ? nl_attr_get_string(attrs[IFA_LABEL])
>                                        : NULL);
> diff --git a/lib/sflow_agent.c b/lib/sflow_agent.c
> index c95f654a5..c19434d6c 100644
> --- a/lib/sflow_agent.c
> +++ b/lib/sflow_agent.c
> @@ -152,15 +152,24 @@ void sfl_agent_tick(SFLAgent *agent, time_t now)
>
>  SFLReceiver *sfl_agent_addReceiver(SFLAgent *agent)
>  {
> -    SFLReceiver *rcv = (SFLReceiver *)sflAlloc(agent, sizeof(SFLReceiver));
> -    sfl_receiver_init(rcv, agent);
> -    /* add to end of list - to preserve the receiver index numbers for 
> existing receivers */
> -    {
> -     SFLReceiver *r, *prev = NULL;
> -     for(r = agent->receivers; r != NULL; prev = r, r = r->nxt);
> -     if(prev) prev->nxt = rcv;
> -     else agent->receivers = rcv;
> -     rcv->nxt = NULL;
> +    SFLReceiver *rcv = (SFLReceiver *) sflAlloc(agent, sizeof(SFLReceiver));
> +    if (rcv) {
> +        sfl_receiver_init(rcv, agent);
> +        /* add to end of list - to preserve the receiver index numbers for
> +         * existing receivers
> +         */
> +        {
> +            SFLReceiver *r, *prev = NULL;
> +            for (r = agent->receivers; r != NULL; prev = r, r = r->nxt) {
> +                /* nothing to do */
> +            }
> +            if (prev) {
> +                prev->nxt = rcv;
> +            } else {
> +                agent->receivers = rcv;
> +            }
> +            rcv->nxt = NULL;
> +        }
>      }
>      return rcv;
>  }
> @@ -202,23 +211,35 @@ SFLSampler *sfl_agent_addSampler(SFLAgent *agent, 
> SFLDataSource_instance *pdsi)
>      /* either we found the insert point, or reached the end of the list...*/
>
>      {
> -     SFLSampler *newsm = (SFLSampler *)sflAlloc(agent, sizeof(SFLSampler));
> -     sfl_sampler_init(newsm, agent, pdsi);
> -     if(prev) prev->nxt = newsm;
> -     else agent->samplers = newsm;
> -     newsm->nxt = sm;
> -
> -     /* see if we should go in the ifIndex jumpTable */
> -     if(SFL_DS_CLASS(newsm->dsi) == 0) {
> -         SFLSampler *test = sfl_agent_getSamplerByIfIndex(agent, 
> SFL_DS_INDEX(newsm->dsi));
> -         if(test && (SFL_DS_INSTANCE(newsm->dsi) < 
> SFL_DS_INSTANCE(test->dsi))) {
> -             /* replace with this new one because it has a lower ds_instance 
> number */
> -             sfl_agent_jumpTableRemove(agent, test);
> -             test = NULL;
> -         }
> -         if(test == NULL) sfl_agent_jumpTableAdd(agent, newsm);
> -     }
> -     return newsm;
> +        SFLSampler *newsm = (SFLSampler *) sflAlloc(agent, 
> sizeof(SFLSampler));
> +        if (newsm) {
> +            memset(newsm, 0, sizeof(*newsm));
> +            sfl_sampler_init(newsm, agent, pdsi);
> +            if (prev) {
> +                prev->nxt = newsm;
> +            } else {
> +                agent->samplers = newsm;
> +            }
> +            newsm->nxt = sm;
> +
> +            /* see if we should go in the ifIndex jumpTable */
> +            if (SFL_DS_CLASS(newsm->dsi) == 0) {
> +                SFLSampler *test = sfl_agent_getSamplerByIfIndex(agent,
> +                                    SFL_DS_INDEX(newsm->dsi));
> +                if (test && (SFL_DS_INSTANCE(newsm->dsi)
> +                            < SFL_DS_INSTANCE(test->dsi))) {
> +                    /* replace with this new one because it has a lower
> +                     * ds_instance number
> +                     */
> +                    sfl_agent_jumpTableRemove(agent, test);
> +                    test = NULL;
> +                }
> +                if (test == NULL) {
> +                    sfl_agent_jumpTableAdd(agent, newsm);
> +                }
> +            }
> +        }
> +        return newsm;
>      }
>  }
>
> @@ -241,12 +262,18 @@ SFLPoller *sfl_agent_addPoller(SFLAgent *agent,
>      }
>      /* either we found the insert point, or reached the end of the list... */
>      {
> -     SFLPoller *newpl = (SFLPoller *)sflAlloc(agent, sizeof(SFLPoller));
> -     sfl_poller_init(newpl, agent, pdsi, magic, getCountersFn);
> -     if(prev) prev->nxt = newpl;
> -     else agent->pollers = newpl;
> -     newpl->nxt = pl;
> -     return newpl;
> +        SFLPoller *newpl = (SFLPoller *) sflAlloc(agent, sizeof(SFLPoller));
> +        if (newpl) {
> +            memset(newpl, 0, sizeof(*newpl));
> +            sfl_poller_init(newpl, agent, pdsi, magic, getCountersFn);
> +            if (prev) {
> +                prev->nxt = newpl;
> +            } else {
> +                agent->pollers = newpl;
> +            }
> +            newpl->nxt = pl;
> +        }
> +        return newpl;
>      }
>  }
>
> diff --git a/lib/shash.c b/lib/shash.c
> index a7b2c6458..adb388cf7 100644
> --- a/lib/shash.c
> +++ b/lib/shash.c
> @@ -194,7 +194,9 @@ shash_replace_nocopy(struct shash *sh, char *name, const 
> void *data)
>  void
>  shash_delete(struct shash *sh, struct shash_node *node)
>  {
> -    free(shash_steal(sh, node));
> +    if (node) {
> +        free(shash_steal(sh, node));
> +    }
>  }
>
>  /* Deletes 'node' from 'sh'.  Neither the node's name nor its data is freed;
> diff --git a/lib/sset.c b/lib/sset.c
> index aa1790020..50f6676df 100644
> --- a/lib/sset.c
> +++ b/lib/sset.c
> @@ -261,8 +261,11 @@ char *
>  sset_pop(struct sset *set)
>  {
>      const char *name = SSET_FIRST(set);
> -    char *copy = xstrdup(name);
> -    sset_delete(set, SSET_NODE_FROM_NAME(name));
> +    char *copy = NULL;
> +    if (name) {
> +        copy = xstrdup(name);
> +        sset_delete(set, SSET_NODE_FROM_NAME(name));
> +    }
>      return copy;
>  }
>
> diff --git a/ovsdb/condition.c b/ovsdb/condition.c
> index d0016fa7f..f36531669 100644
> --- a/ovsdb/condition.c
> +++ b/ovsdb/condition.c
> @@ -47,7 +47,15 @@ ovsdb_clause_from_json(const struct ovsdb_table_schema *ts,
>
>          /* Column and arg fields are not being used with boolean functions.
>           * Use dummy values */
> -        clause->column = ovsdb_table_schema_get_column(ts, "_uuid");
> +        const struct ovsdb_column *uuid_column;
> +        uuid_column = ovsdb_table_schema_get_column(ts, "_uuid");
> +        if (uuid_column) {
> +            clause->column = uuid_column;
> +        } else {
> +            return ovsdb_syntax_error(json,
> +                                      "unknown column",
> +                                      "No column _uuid in table schema.");
> +        }
>          clause->index = clause->column->index;
>          ovsdb_datum_init_default(&clause->arg, &clause->column->type);
>          return NULL;
> diff --git a/ovsdb/file.c b/ovsdb/file.c
> index 2d887e53e..bccb76098 100644
> --- a/ovsdb/file.c
> +++ b/ovsdb/file.c
> @@ -522,7 +522,12 @@ ovsdb_file_txn_add_row(struct ovsdb_file_txn *ftxn,
>      }
>
>      if (row) {
> -        struct ovsdb_table *table = new ? new->table : old->table;
> +        struct ovsdb_table *table = NULL;
> +        if (new) {
> +            table = new->table;
> +        } else if (old) {
> +            table = old->table;
> +        }
>          char uuid[UUID_LEN + 1];
>
>          if (table != ftxn->table) {
> @@ -533,14 +538,23 @@ ovsdb_file_txn_add_row(struct ovsdb_file_txn *ftxn,
>
>              /* Create JSON object for transaction on this table. */
>              ftxn->table_json = json_object_create();
> -            ftxn->table = table;
> -            json_object_put(ftxn->json, table->schema->name, 
> ftxn->table_json);
> +            if (table) {
> +                ftxn->table = table;
> +                json_object_put(ftxn->json, table->schema->name,
> +                                ftxn->table_json);
> +            }
>          }
>
>          /* Add row to transaction for this table. */
> -        snprintf(uuid, sizeof uuid,
> -                 UUID_FMT, UUID_ARGS(ovsdb_row_get_uuid(new ? new : old)));
> -        json_object_put(ftxn->table_json, uuid, row);
> +        if (new) {
> +            snprintf(uuid, sizeof uuid,
> +                     UUID_FMT, UUID_ARGS(ovsdb_row_get_uuid(new)));
> +            json_object_put(ftxn->table_json, uuid, row);
> +        } else if (old) {
> +            snprintf(uuid, sizeof uuid,
> +                     UUID_FMT, UUID_ARGS(ovsdb_row_get_uuid(old)));
> +            json_object_put(ftxn->table_json, uuid, row);
> +        }
>      }
>  }
>  
> diff --git a/ovsdb/jsonrpc-server.c b/ovsdb/jsonrpc-server.c
> index 17868f5b7..b1cbaa227 100644
> --- a/ovsdb/jsonrpc-server.c
> +++ b/ovsdb/jsonrpc-server.c
> @@ -1038,7 +1038,7 @@ ovsdb_jsonrpc_session_got_request(struct 
> ovsdb_jsonrpc_session *s,
>                                               request->id);
>      } else if (!strcmp(request->method, "get_schema")) {
>          struct ovsdb *db = ovsdb_jsonrpc_lookup_db(s, request, &reply);
> -        if (!reply) {
> +        if (db && !reply) {
>              reply = jsonrpc_create_reply(ovsdb_schema_to_json(db->schema),
>                                           request->id);
>          }
> @@ -1131,6 +1131,8 @@ static void
>  ovsdb_jsonrpc_trigger_create(struct ovsdb_jsonrpc_session *s, struct ovsdb 
> *db,
>                               struct jsonrpc_msg *request)
>  {
> +    ovs_assert(db);
> +
>      /* Check for duplicate ID. */
>      size_t hash = json_hash(request->id, 0);
>      struct ovsdb_jsonrpc_trigger *t
> @@ -1391,6 +1393,7 @@ ovsdb_jsonrpc_monitor_create(struct 
> ovsdb_jsonrpc_session *s, struct ovsdb *db,
>                               enum ovsdb_monitor_version version,
>                               const struct json *request_id)
>  {
> +    ovs_assert(db);
>      struct ovsdb_jsonrpc_monitor *m = NULL;
>      struct ovsdb_monitor *dbmon = NULL;
>      struct json *monitor_id, *monitor_requests;
> diff --git a/ovsdb/monitor.c b/ovsdb/monitor.c
> index 191befcae..1ea92cc0f 100644
> --- a/ovsdb/monitor.c
> +++ b/ovsdb/monitor.c
> @@ -478,7 +478,9 @@ ovsdb_monitor_add_column(struct ovsdb_monitor *dbmon,
>      struct ovsdb_monitor_column *c;
>
>      mt = shash_find_data(&dbmon->tables, table->schema->name);
> -
> +    if (!mt) {
> +        return NULL;
> +    }
>      /* Check for column duplication. Return duplicated column name. */
>      if (mt->columns_index_map[column->index] != -1) {
>          return column->name;
> @@ -781,11 +783,15 @@ ovsdb_monitor_table_condition_update(
>                              const struct json *cond_json)
>  {
>      if (!condition) {
> -        return NULL;
> +        return ovsdb_syntax_error(cond_json, NULL,
> +                                  "Parse error, condition empty.");
>      }
>
>      struct ovsdb_monitor_table_condition *mtc =
>          shash_find_data(&condition->tables, table->schema->name);
> +    if (!mtc) {
> +        return NULL;
> +    }
>      struct ovsdb_error *error;
>      struct ovsdb_condition cond = OVSDB_CONDITION_INITIALIZER(&cond);
>
> @@ -1279,7 +1285,9 @@ ovsdb_monitor_table_add_select(struct ovsdb_monitor 
> *dbmon,
>      struct ovsdb_monitor_table * mt;
>
>      mt = shash_find_data(&dbmon->tables, table->schema->name);
> -    mt->select |= select;
> +    if (mt) {
> +        mt->select |= select;
> +    }
>  }
>
>   /*
> @@ -1329,8 +1337,23 @@ ovsdb_monitor_changes_update(const struct ovsdb_row 
> *old,
>                               const struct ovsdb_monitor_table *mt,
>                               struct ovsdb_monitor_change_set_for_table *mcst)
>  {
> -    const struct uuid *uuid = ovsdb_row_get_uuid(new ? new : old);
> -    struct ovsdb_monitor_row *change;
> +    const struct uuid *uuid = NULL;
> +
> +    if (!new && !old) {
> +        return;
> +    } else {
> +        if (new) {
> +            uuid = ovsdb_row_get_uuid(new);
> +        } else if (old) {
> +            uuid = ovsdb_row_get_uuid(old);
> +        }
> +    }
> +
> +    if (!uuid) {
> +        return;
> +    }
> +
> +    struct ovsdb_monitor_row *change = NULL;
>
>      change = ovsdb_monitor_changes_row_find(mcst, uuid);
>      if (!change) {
> @@ -1657,15 +1680,21 @@ ovsdb_monitor_hash(const struct ovsdb_monitor *dbmon, 
> size_t basis)
>      nodes = shash_sort(&dbmon->tables);
>      n = shash_count(&dbmon->tables);
>
> +    if (!nodes) {
> +        return basis;
> +    }
> +
>      for (i = 0; i < n; i++) {
>          struct ovsdb_monitor_table *mt = nodes[i]->data;
>
> -        basis = hash_pointer(mt->table, basis);
> -        basis = hash_3words(mt->select, mt->n_columns, basis);
> +        if (mt) {
> +            basis = hash_pointer(mt->table, basis);
> +            basis = hash_3words(mt->select, mt->n_columns, basis);
>
> -        for (j = 0; j < mt->n_columns; j++) {
> -            basis = hash_pointer(mt->columns[j].column, basis);
> -            basis = hash_2words(mt->columns[j].select, basis);
> +            for (j = 0; j < mt->n_columns; j++) {
> +                basis = hash_pointer(mt->columns[j].column, basis);
> +                basis = hash_2words(mt->columns[j].select, basis);
> +            }
>          }
>      }
>      free(nodes);
> diff --git a/ovsdb/ovsdb-client.c b/ovsdb/ovsdb-client.c
> index f1b8d6491..ca2becd8d 100644
> --- a/ovsdb/ovsdb-client.c
> +++ b/ovsdb/ovsdb-client.c
> @@ -1223,17 +1223,25 @@ parse_monitor_columns(char *arg, const char *server, 
> const char *database,
>
>          n = shash_count(&table->columns);
>          nodes = shash_sort(&table->columns);
> -        for (i = 0; i < n; i++) {
> -            const struct ovsdb_column *column = nodes[i]->data;
> -            if (column->index != OVSDB_COL_UUID
> -                && column->index != OVSDB_COL_VERSION) {
> -                add_column(server, column, columns, columns_json);
> +        if (nodes) {
> +            for (i = 0; i < n; i++) {
> +                const struct ovsdb_column *column = nodes[i]->data;
> +                if (column->index != OVSDB_COL_UUID
> +                    && column->index != OVSDB_COL_VERSION) {
> +                    add_column(server, column, columns, columns_json);
> +                }
>              }
> +            free(nodes);
>          }
> -        free(nodes);
>
> -        add_column(server, ovsdb_table_schema_get_column(table, "_version"),
> -                   columns, columns_json);
> +        const struct ovsdb_column *version_column =
> +                            ovsdb_table_schema_get_column(table, "_version");
> +
> +        if (version_column) {
> +            add_column(server, version_column, columns, columns_json);
> +        } else {
> +            VLOG_ERR("Table does not contain _version column.");
> +        }
>      }
>
>      if (!initial || !insert || !delete || !modify) {
> @@ -1439,14 +1447,16 @@ do_monitor__(struct jsonrpc *rpc, const char 
> *database,
>              ovs_fatal(0, "ALL tables are not allowed with condition");
>          }
>
> -        for (i = 0; i < n; i++) {
> -            struct ovsdb_table_schema *table = nodes[i]->data;
> +        if (nodes) {
> +            for (i = 0; i < n; i++) {
> +                struct ovsdb_table_schema *table = nodes[i]->data;
>
> -            add_monitored_table(argc, argv, server, database, NULL, table,
> -                                monitor_requests,
> -                                &mts, &n_mts, &allocated_mts);
> +                add_monitored_table(argc, argv, server, database, NULL, 
> table,
> +                                    monitor_requests,
> +                                    &mts, &n_mts, &allocated_mts);
> +            }
> +            free(nodes);
>          }
> -        free(nodes);
>      }
>
>      send_db_change_aware(rpc);
> @@ -1870,6 +1880,10 @@ do_dump(struct jsonrpc *rpc, const char *database,
>          n_tables = shash_count(&schema->tables);
>      }
>
> +    if (!tables) {
> +        goto end;
> +    }
> +
>      /* Construct transaction to retrieve entire database. */
>      transaction = json_array_create_1(json_string_create(database));
>      for (i = 0; i < n_tables; i++) {
> @@ -1929,8 +1943,9 @@ do_dump(struct jsonrpc *rpc, const char *database,
>      }
>
>      jsonrpc_msg_destroy(reply);
> -    shash_destroy(&custom_columns);
>      free(tables);
> +end:
> +    shash_destroy(&custom_columns);
>      ovsdb_schema_destroy(schema);
>  }
>
> diff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c
> index 33ca4910d..02e024de4 100644
> --- a/ovsdb/ovsdb-server.c
> +++ b/ovsdb/ovsdb-server.c
> @@ -1784,14 +1784,16 @@ ovsdb_server_list_databases(struct unixctl_conn 
> *conn, int argc OVS_UNUSED,
>      ds_init(&s);
>
>      nodes = shash_sort(all_dbs);
> -    for (i = 0; i < shash_count(all_dbs); i++) {
> -        const struct shash_node *node = nodes[i];
> -        struct db *db = node->data;
> -        if (db->db) {
> -            ds_put_format(&s, "%s\n", node->name);
> +    if (nodes) {
> +        for (i = 0; i < shash_count(all_dbs); i++) {
> +            const struct shash_node *node = nodes[i];
> +            struct db *db = node->data;
> +            if (db->db) {
> +                ds_put_format(&s, "%s\n", node->name);
> +            }
>          }
> +        free(nodes);
>      }
> -    free(nodes);
>
>      unixctl_command_reply(conn, ds_cstr(&s));
>      ds_destroy(&s);
> @@ -2191,6 +2193,7 @@ save_config(struct server_config *config)
>  static void
>  sset_from_json(struct sset *sset, const struct json *array)
>  {
> +    ovs_assert(array);
>      size_t i;
>
>      sset_clear(sset);
> diff --git a/ovsdb/ovsdb-util.c b/ovsdb/ovsdb-util.c
> index 303191dc8..148230da8 100644
> --- a/ovsdb/ovsdb-util.c
> +++ b/ovsdb/ovsdb-util.c
> @@ -291,6 +291,15 @@ ovsdb_util_write_string_string_column(struct ovsdb_row 
> *row,
>      size_t i;
>
>      column = ovsdb_table_schema_get_column(row->table->schema, column_name);
> +    if (!column) {
> +        VLOG_ERR("No %s column present in the %s table",
> +                 column_name, row->table->schema->name);
> +        for (i = 0; i < n; i++) {
> +            free(keys[i]);
> +            free(values[i]);
> +        }
> +        return;
> +    }
>      datum = ovsdb_util_get_datum(row, column_name, OVSDB_TYPE_STRING,
>                                  OVSDB_TYPE_STRING, UINT_MAX);
>      if (!datum) {
> diff --git a/ovsdb/ovsdb.c b/ovsdb/ovsdb.c
> index afec96264..6dcfc5751 100644
> --- a/ovsdb/ovsdb.c
> +++ b/ovsdb/ovsdb.c
> @@ -195,7 +195,7 @@ root_set_size(const struct ovsdb_schema *schema)
>  struct ovsdb_error *
>  ovsdb_schema_from_json(const struct json *json, struct ovsdb_schema 
> **schemap)
>  {
> -    struct ovsdb_schema *schema;
> +    struct ovsdb_schema *schema = NULL;
>      const struct json *name, *tables, *version_json, *cksum;
>      struct ovsdb_error *error;
>      struct shash_node *node;
> @@ -215,78 +215,86 @@ ovsdb_schema_from_json(const struct json *json, struct 
> ovsdb_schema **schemap)
>          return error;
>      }
>
> -    if (version_json) {
> -        version = json_string(version_json);
> -        if (!ovsdb_is_valid_version(version)) {
> -            return ovsdb_syntax_error(json, NULL, "schema version \"%s\" not 
> "
> -                                      "in format x.y.z", version);
> +    if (name && tables) {
> +        if (version_json) {
> +            version = json_string(version_json);
> +            if (!ovsdb_is_valid_version(version)) {
> +                return ovsdb_syntax_error(json, NULL,
> +                                          "schema version \"%s\" not "
> +                                          "in format x.y.z", version);
> +            }
> +        } else {
> +            /* Backward compatibility with old databases. */
> +            version = "";
>          }
> -    } else {
> -        /* Backward compatibility with old databases. */
> -        version = "";
> -    }
>
> -    schema = ovsdb_schema_create(json_string(name), version,
> -                                 cksum ? json_string(cksum) : "");
> -    SHASH_FOR_EACH (node, json_object(tables)) {
> -        struct ovsdb_table_schema *table;
> +        schema = ovsdb_schema_create(json_string(name), version,
> +                                    cksum ? json_string(cksum) : "");
> +        SHASH_FOR_EACH (node, json_object(tables)) {
> +            struct ovsdb_table_schema *table;
> +
> +            if (node->name[0] == '_') {
> +                error = ovsdb_syntax_error(json, NULL, "names beginning with 
> "
> +                                        "\"_\" are reserved");
> +            } else if (!ovsdb_parser_is_id(node->name)) {
> +                error = ovsdb_syntax_error(json, NULL,
> +                                           "name must be a valid id");
> +            } else {
> +                error = ovsdb_table_schema_from_json(node->data, node->name,
> +                                                    &table);
> +            }
> +            if (error) {
> +                ovsdb_schema_destroy(schema);
> +                return error;
> +            }
>
> -        if (node->name[0] == '_') {
> -            error = ovsdb_syntax_error(json, NULL, "names beginning with "
> -                                       "\"_\" are reserved");
> -        } else if (!ovsdb_parser_is_id(node->name)) {
> -            error = ovsdb_syntax_error(json, NULL, "name must be a valid 
> id");
> -        } else {
> -            error = ovsdb_table_schema_from_json(node->data, node->name,
> -                                                 &table);
> -        }
> -        if (error) {
> -            ovsdb_schema_destroy(schema);
> -            return error;
> +            shash_add(&schema->tables, table->name, table);
>          }
> -
> -        shash_add(&schema->tables, table->name, table);
>      }
>
> -    /* "isRoot" was not part of the original schema definition.  Before it 
> was
> -     * added, there was no support for garbage collection.  So, for backward
> -     * compatibility, if the root set is empty then assume that every table 
> is
> -     * in the root set. */
> -    if (root_set_size(schema) == 0) {
> -        SHASH_FOR_EACH (node, &schema->tables) {
> -            struct ovsdb_table_schema *table = node->data;
> -
> -            table->is_root = true;
> +    if (schema) {
> +        /* "isRoot" was not part of the original schema definition.  Before 
> it
> +        * was added, there was no support for garbage collection.  So, for
> +        * backward compatibility, if the root set is empty then assume that
> +        * every table is in the root set. */
> +        if (root_set_size(schema) == 0) {
> +            SHASH_FOR_EACH (node, &schema->tables) {
> +                struct ovsdb_table_schema *table = node->data;
> +
> +                table->is_root = true;
> +            }
>          }
> -    }
>
> -    /* Validate that all refTables refer to the names of tables that exist.
> -     *
> -     * Also force certain columns to be persistent, as explained in
> -     * ovsdb_schema_check_ref_table().  This requires 'is_root' to be known, 
> so
> -     * this must follow the loop updating 'is_root' above. */
> -    SHASH_FOR_EACH (node, &schema->tables) {
> -        struct ovsdb_table_schema *table = node->data;
> -        struct shash_node *node2;
> +        /* Validate that all refTables refer to the names of tables that 
> exist.
> +        *
> +        * Also force certain columns to be persistent, as explained in
> +        * ovsdb_schema_check_ref_table().  This requires 'is_root' to be
> +        * known, so this must follow the loop updating 'is_root' above. */
> +        SHASH_FOR_EACH (node, &schema->tables) {
> +            struct ovsdb_table_schema *table = node->data;
> +            struct shash_node *node2;
>
> -        SHASH_FOR_EACH (node2, &table->columns) {
> -            struct ovsdb_column *column = node2->data;
> +            SHASH_FOR_EACH (node2, &table->columns) {
> +                struct ovsdb_column *column = node2->data;
>
> -            error = ovsdb_schema_check_ref_table(column, &schema->tables,
> -                                                 &column->type.key, "key");
> -            if (!error) {
>                  error = ovsdb_schema_check_ref_table(column, &schema->tables,
> -                                                     &column->type.value,
> -                                                     "value");
> -            }
> -            if (error) {
> -                ovsdb_schema_destroy(schema);
> -                return error;
> +                                                    &column->type.key, 
> "key");
> +                if (!error) {
> +                    error = ovsdb_schema_check_ref_table(column,
> +                                                        &schema->tables,
> +                                                        &column->type.value,
> +                                                        "value");
> +                }
> +                if (error) {
> +                    ovsdb_schema_destroy(schema);
> +                    return error;
> +                }
>              }
>          }
> +
> +        *schemap = schema;
>      }
>
> -    *schemap = schema;
>      return NULL;
>  }
>
> diff --git a/ovsdb/query.c b/ovsdb/query.c
> index eebe56412..0129eb038 100644
> --- a/ovsdb/query.c
> +++ b/ovsdb/query.c
> @@ -91,7 +91,9 @@ ovsdb_query_distinct(struct ovsdb_table *table,
>          struct ovsdb_row_hash hash;
>
>          ovsdb_row_hash_init(&hash, columns);
> -        ovsdb_query(table, condition, query_distinct_cb, &hash);
> +        if (condition) {
> +            ovsdb_query(table, condition, query_distinct_cb, &hash);
> +        }
>          HMAP_FOR_EACH (node, hmap_node, &hash.rows) {
>              ovsdb_row_set_add_row(results, node->row);
>          }
> diff --git a/ovsdb/replication.c b/ovsdb/replication.c
> index 477c69d70..f5e150c33 100644
> --- a/ovsdb/replication.c
> +++ b/ovsdb/replication.c
> @@ -575,15 +575,17 @@ create_monitor_request(struct ovsdb_schema *schema)
>      size_t n = shash_count(&schema->tables);
>      const struct shash_node **nodes = shash_sort(&schema->tables);
>
> -    for (int j = 0; j < n; j++) {
> -        struct ovsdb_table_schema *table = nodes[j]->data;
> +    if (nodes) {
> +        for (int j = 0; j < n; j++) {
> +            struct ovsdb_table_schema *table = nodes[j]->data;
>
> -        /* Monitor all tables not excluded. */
> -        if (!excluded_tables_find(db_name, table->name)) {
> -            add_monitored_table(table, monitor_request);
> +            /* Monitor all tables not excluded. */
> +            if (!excluded_tables_find(db_name, table->name)) {
> +                add_monitored_table(table, monitor_request);
> +            }
>          }
> +        free(nodes);
>      }
> -    free(nodes);
>
>      /* Create a monitor request. */
>      monitor = json_array_create_3(
> diff --git a/ovsdb/row.c b/ovsdb/row.c
> index d7bfbdd36..9f87c832a 100644
> --- a/ovsdb/row.c
> +++ b/ovsdb/row.c
> @@ -399,7 +399,9 @@ ovsdb_row_set_add_row(struct ovsdb_row_set *set, const 
> struct ovsdb_row *row)
>          set->rows = x2nrealloc(set->rows, &set->allocated_rows,
>                                 sizeof *set->rows);
>      }
> -    set->rows[set->n_rows++] = row;
> +    if (set->rows) {
> +        set->rows[set->n_rows++] = row;
> +    }
>  }
>
>  struct json *
> diff --git a/ovsdb/table.c b/ovsdb/table.c
> index 66071ce2f..990d49ea4 100644
> --- a/ovsdb/table.c
> +++ b/ovsdb/table.c
> @@ -158,7 +158,7 @@ ovsdb_table_schema_from_json(const struct json *json, 
> const char *name,
>          n_max_rows = UINT_MAX;
>      }
>
> -    if (shash_is_empty(json_object(columns))) {
> +    if (!columns || shash_is_empty(json_object(columns))) {
>          return ovsdb_syntax_error(json, NULL,
>                                    "table must have at least one column");
>      }
> diff --git a/ovsdb/transaction.c b/ovsdb/transaction.c
> index 03541af85..43b104f31 100644
> --- a/ovsdb/transaction.c
> +++ b/ovsdb/transaction.c
> @@ -576,9 +576,11 @@ ovsdb_txn_update_weak_refs(struct ovsdb_txn *txn 
> OVS_UNUSED,
>          dst_row = CONST_CAST(struct ovsdb_row *,
>                      ovsdb_table_get_row(weak->dst_table, &weak->dst));
>
> -        ovs_assert(!ovsdb_row_find_weak_ref(dst_row, weak));
> -        hmap_insert(&dst_row->dst_refs, &weak->dst_node,
> -                    ovsdb_weak_ref_hash(weak));
> +        if (dst_row) {
> +            ovs_assert(!ovsdb_row_find_weak_ref(dst_row, weak));
> +            hmap_insert(&dst_row->dst_refs, &weak->dst_node,
> +                        ovsdb_weak_ref_hash(weak));
> +        }
>          ovs_list_remove(&weak->src_node);
>          ovs_list_init(&weak->src_node);
>      }
> diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c
> index 2f5ac1a26..991b426b9 100644
> --- a/utilities/ovs-vsctl.c
> +++ b/utilities/ovs-vsctl.c
> @@ -334,8 +334,11 @@ parse_options(int argc, char *argv[], struct shash 
> *local_options)
>              exit(EXIT_SUCCESS);
>
>          case 't':
> -            if (!str_to_uint(optarg, 10, &timeout) || !timeout) {
> -                ctl_fatal("value %s on -t or --timeout is invalid", optarg);
> +            if (optarg) {
> +                if (!str_to_uint(optarg, 10, &timeout) || !timeout) {
> +                    ctl_fatal("value %s on -t or --timeout is invalid",
> +                              optarg);
> +                }
>              }
>              break;
>
> @@ -349,11 +352,15 @@ parse_options(int argc, char *argv[], struct shash 
> *local_options)
>          STREAM_SSL_OPTION_HANDLERS
>
>          case OPT_PEER_CA_CERT:
> -            stream_ssl_set_peer_ca_cert_file(optarg);
> +            if (optarg) {
> +                stream_ssl_set_peer_ca_cert_file(optarg);
> +            }
>              break;
>
>          case OPT_BOOTSTRAP_CA_CERT:
> -            stream_ssl_set_ca_cert_file(optarg, true);
> +            if (optarg) {
> +                stream_ssl_set_ca_cert_file(optarg, true);
> +            }
>              break;
>
>          case '?':
> @@ -575,7 +582,7 @@ add_bridge_to_cache(struct vsctl_context *vsctl_ctx,
>                      struct ovsrec_bridge *br_cfg, const char *name,
>                      struct vsctl_bridge *parent, int vlan)
>  {
> -    struct vsctl_bridge *br = xmalloc(sizeof *br);
> +    struct vsctl_bridge *br = xzalloc(sizeof *br);
>      br->br_cfg = br_cfg;
>      br->name = xstrdup(name);
>      ovs_list_init(&br->ports);
> @@ -659,7 +666,7 @@ static struct vsctl_port *
>  add_port_to_cache(struct vsctl_context *vsctl_ctx, struct vsctl_bridge 
> *parent,
>                    struct ovsrec_port *port_cfg)
>  {
> -    struct vsctl_port *port;
> +    struct vsctl_port *port = xzalloc(sizeof *port);
>
>      if (port_cfg->tag
>          && *port_cfg->tag >= 0 && *port_cfg->tag <= 4095) {
> @@ -671,11 +678,13 @@ add_port_to_cache(struct vsctl_context *vsctl_ctx, 
> struct vsctl_bridge *parent,
>          }
>      }
>
> -    port = xmalloc(sizeof *port);
> -    ovs_list_push_back(&parent->ports, &port->ports_node);
> +    if (parent) {
> +        ovs_list_push_back(&parent->ports, &port->ports_node);
> +        port->bridge = parent;
> +    }
> +
>      ovs_list_init(&port->ifaces);
>      port->port_cfg = port_cfg;
> -    port->bridge = parent;
>      shash_add(&vsctl_ctx->ports, port_cfg->name, port);
>
>      return port;
> @@ -818,55 +827,63 @@ vsctl_context_populate_cache(struct ctl_context *ctx)
>              continue;
>          }
>          br = shash_find_data(&vsctl_ctx->bridges, br_cfg->name);
> -        for (j = 0; j < br_cfg->n_ports; j++) {
> -            struct ovsrec_port *port_cfg = br_cfg->ports[j];
> -            struct vsctl_port *port;
> -            size_t k;
> -
> -            port = shash_find_data(&vsctl_ctx->ports, port_cfg->name);
> -            if (port) {
> -                if (port_cfg == port->port_cfg) {
> -                    VLOG_WARN("%s: port is in multiple bridges (%s and %s)",
> -                              port_cfg->name, br->name, port->bridge->name);
> -                } else {
> -                    /* Log as an error because this violates the database's
> -                     * uniqueness constraints, so the database server 
> shouldn't
> -                     * have allowed it. */
> -                    VLOG_ERR("%s: database contains duplicate port name",
> -                             port_cfg->name);
> -                }
> -                continue;
> -            }
> -
> -            if (port_is_fake_bridge(port_cfg)
> -                && !sset_add(&bridges, port_cfg->name)) {
> -                continue;
> -            }
> -
> -            port = add_port_to_cache(vsctl_ctx, br, port_cfg);
> -            for (k = 0; k < port_cfg->n_interfaces; k++) {
> -                struct ovsrec_interface *iface_cfg = port_cfg->interfaces[k];
> -                struct vsctl_iface *iface;
> -
> -                iface = shash_find_data(&vsctl_ctx->ifaces, iface_cfg->name);
> -                if (iface) {
> -                    if (iface_cfg == iface->iface_cfg) {
> -                        VLOG_WARN("%s: interface is in multiple ports "
> -                                  "(%s and %s)",
> -                                  iface_cfg->name,
> -                                  iface->port->port_cfg->name,
> -                                  port->port_cfg->name);
> +        if (br) {
> +            for (j = 0; j < br_cfg->n_ports; j++) {
> +                struct ovsrec_port *port_cfg = br_cfg->ports[j];
> +                struct vsctl_port *port;
> +                size_t k;
> +
> +                port = shash_find_data(&vsctl_ctx->ports, port_cfg->name);
> +                if (port) {
> +                    if (port_cfg == port->port_cfg) {
> +                        VLOG_WARN("%s: port is in multiple bridges "
> +                                "(%s and %s)", port_cfg->name, br->name,
> +                                port->bridge->name);
>                      } else {
>                          /* Log as an error because this violates the 
> database's
> -                         * uniqueness constraints, so the database server
> -                         * shouldn't have allowed it. */
> -                        VLOG_ERR("%s: database contains duplicate interface "
> -                                 "name", iface_cfg->name);
> +                        * uniqueness constraints, so the database server
> +                        * shouldn't have allowed it. */
> +                        VLOG_ERR("%s: database contains duplicate port name",
> +                                port_cfg->name);
>                      }
>                      continue;
>                  }
>
> -                add_iface_to_cache(vsctl_ctx, port, iface_cfg);
> +                if (port_is_fake_bridge(port_cfg)
> +                    && !sset_add(&bridges, port_cfg->name)) {
> +                    continue;
> +                }
> +
> +                port = add_port_to_cache(vsctl_ctx, br, port_cfg);
> +                if (port) {
> +                    for (k = 0; k < port_cfg->n_interfaces; k++) {
> +                        struct ovsrec_interface *iface_cfg =
> +                                                port_cfg->interfaces[k];
> +                        struct vsctl_iface *iface;
> +
> +                        iface = shash_find_data(&vsctl_ctx->ifaces,
> +                                                iface_cfg->name);
> +                        if (iface) {
> +                            if (iface_cfg == iface->iface_cfg) {
> +                                VLOG_WARN("%s: interface is in multiple 
> ports "
> +                                        "(%s and %s)",
> +                                        iface_cfg->name,
> +                                        iface->port->port_cfg->name,
> +                                        port->port_cfg->name);
> +                            } else {
> +                                /* Log as an error because this violates the
> +                                * database's uniqueness constraints, so the
> +                                * database server shouldn't have allowed it.
> +                                */
> +                                VLOG_ERR("%s: database contains duplicate "
> +                                        "interface name", iface_cfg->name);
> +                            }
> +                            continue;
> +                        }
> +
> +                        add_iface_to_cache(vsctl_ctx, port, iface_cfg);
> +                    }
> +                }
>              }
>          }
>      }
> @@ -889,14 +906,23 @@ check_conflicts(struct vsctl_context *vsctl_ctx, const 
> char *name,
>
>      port = shash_find_data(&vsctl_ctx->ports, name);
>      if (port) {
> -        ctl_fatal("%s because a port named %s already exists on "
> -                    "bridge %s", msg, name, port->bridge->name);
> +        if (port->bridge) {
> +            ctl_fatal("%s because a port named %s already exists on "
> +                      "bridge %s", msg, name, port->bridge->name);
> +        } else {
> +            ctl_fatal("%s because a port named %s already exists", msg, 
> name);
> +        }
>      }
>
>      iface = shash_find_data(&vsctl_ctx->ifaces, name);
>      if (iface) {
> -        ctl_fatal("%s because an interface named %s already exists "
> -                    "on bridge %s", msg, name, iface->port->bridge->name);
> +        if (iface->port->bridge) {
> +            ctl_fatal("%s because an interface named %s already exists "
> +                      "on bridge %s", msg, name, iface->port->bridge->name);
> +        } else {
> +            ctl_fatal("%s because an interface named %s already exists", msg,
> +                      name);
> +        }
>      }
>
>      free(msg);
> @@ -936,7 +962,7 @@ find_port(struct vsctl_context *vsctl_ctx, const char 
> *name, bool must_exist)
>      ovs_assert(vsctl_ctx->cache_valid);
>
>      port = shash_find_data(&vsctl_ctx->ports, name);
> -    if (port && !strcmp(name, port->bridge->name)) {
> +    if (port && port->bridge && !strcmp(name, port->bridge->name)) {
>          port = NULL;
>      }
>      if (must_exist && !port) {
> @@ -954,7 +980,8 @@ find_iface(struct vsctl_context *vsctl_ctx, const char 
> *name, bool must_exist)
>      ovs_assert(vsctl_ctx->cache_valid);
>
>      iface = shash_find_data(&vsctl_ctx->ifaces, name);
> -    if (iface && !strcmp(name, iface->port->bridge->name)) {
> +    if (iface && iface->port->bridge &&
> +        !strcmp(name, iface->port->bridge->name)) {
>          iface = NULL;
>      }
>      if (must_exist && !iface) {
> @@ -1679,14 +1706,16 @@ get_external_id(struct smap *smap, const char 
> *prefix, const char *key,
>          size_t prefix_len = strlen(prefix);
>          size_t i;
>
> -        for (i = 0; i < smap_count(smap); i++) {
> -            const struct smap_node *node = sorted[i];
> -            if (!strncmp(node->key, prefix, prefix_len)) {
> -                ds_put_format(output, "%s=%s\n", node->key + prefix_len,
> -                              node->value);
> +        if (sorted) {
> +            for (i = 0; i < smap_count(smap); i++) {
> +                const struct smap_node *node = sorted[i];
> +                if (!strncmp(node->key, prefix, prefix_len)) {
> +                    ds_put_format(output, "%s=%s\n", node->key + prefix_len,
> +                                node->value);
> +                }
>              }
> +            free(sorted);
>          }
> -        free(sorted);
>      }
>  }
>
> diff --git a/vtep/vtep-ctl.c b/vtep/vtep-ctl.c
> index e5d99714d..356840089 100644
> --- a/vtep/vtep-ctl.c
> +++ b/vtep/vtep-ctl.c
> @@ -250,8 +250,11 @@ parse_options(int argc, char *argv[], struct shash 
> *local_options)
>              exit(EXIT_SUCCESS);
>
>          case 't':
> -            if (!str_to_uint(optarg, 10, &timeout) || !timeout) {
> -                ctl_fatal("value %s on -t or --timeout is invalid", optarg);
> +            if (optarg) {
> +                if (!str_to_uint(optarg, 10, &timeout) || !timeout) {
> +                    ctl_fatal("value %s on -t or --timeout is invalid",
> +                              optarg);
> +                }
>              }
>              break;
>
> @@ -1065,42 +1068,46 @@ vtep_ctl_context_populate_cache(struct ctl_context 
> *ctx)
>              continue;
>          }
>          ps = shash_find_data(&vtepctl_ctx->pswitches, ps_cfg->name);
> -        for (j = 0; j < ps_cfg->n_ports; j++) {
> -            struct vteprec_physical_port *port_cfg = ps_cfg->ports[j];
> -            struct vtep_ctl_port *port;
> -            size_t k;
> -
> -            port = shash_find_data(&vtepctl_ctx->ports, port_cfg->name);
> -            if (port) {
> -                if (port_cfg == port->port_cfg) {
> -                    VLOG_WARN("%s: port is in multiple physical switches "
> -                              "(%s and %s)",
> -                              port_cfg->name, ps->name, port->ps->name);
> -                } else {
> -                    /* Log as an error because this violates the database's
> -                     * uniqueness constraints, so the database server 
> shouldn't
> -                     * have allowed it. */
> -                    VLOG_ERR("%s: database contains duplicate port name",
> -                             port_cfg->name);
> +        if (ps) {
> +            for (j = 0; j < ps_cfg->n_ports; j++) {
> +                struct vteprec_physical_port *port_cfg = ps_cfg->ports[j];
> +                struct vtep_ctl_port *port;
> +                size_t k;
> +
> +                port = shash_find_data(&vtepctl_ctx->ports, port_cfg->name);
> +                if (port) {
> +                    if (port_cfg == port->port_cfg) {
> +                        VLOG_WARN("%s: port is in multiple physical switches 
> "
> +                                "(%s and %s)",
> +                                port_cfg->name, ps->name, port->ps->name);
> +                    } else {
> +                        /* Log as an error because this violates the 
> database's
> +                        * uniqueness constraints, so the database server
> +                        * shouldn't have allowed it. */
> +                        VLOG_ERR("%s: database contains duplicate port name",
> +                                port_cfg->name);
> +                    }
> +                    continue;
>                  }
> -                continue;
> -            }
>
> -            port = add_port_to_cache(vtepctl_ctx, ps, port_cfg);
> +                port = add_port_to_cache(vtepctl_ctx, ps, port_cfg);
> +                if (port) {
> +                    for (k = 0; k < port_cfg->n_vlan_bindings; k++) {
> +                        struct vtep_ctl_lswitch *ls;
> +                        char *vlan;
>
> -            for (k = 0; k < port_cfg->n_vlan_bindings; k++) {
> -                struct vtep_ctl_lswitch *ls;
> -                char *vlan;
> +                        vlan = xasprintf("%"PRId64,
> +                                         port_cfg->key_vlan_bindings[k]);
> +                        if (shash_find(&port->bindings, vlan)) {
> +                            ctl_fatal("multiple bindings for vlan %s", vlan);
> +                        }
>
> -                vlan = xasprintf("%"PRId64, port_cfg->key_vlan_bindings[k]);
> -                if (shash_find(&port->bindings, vlan)) {
> -                    ctl_fatal("multiple bindings for vlan %s", vlan);
> -                }
> -
> -                ls_cfg = port_cfg->value_vlan_bindings[k];
> -                ls = find_lswitch(vtepctl_ctx, ls_cfg->name, true);
> +                        ls_cfg = port_cfg->value_vlan_bindings[k];
> +                        ls = find_lswitch(vtepctl_ctx, ls_cfg->name, true);
>
> -                shash_add_nocopy(&port->bindings, vlan, ls);
> +                        shash_add_nocopy(&port->bindings, vlan, ls);
> +                    }
> +                }
>              }
>          }
>      }
> @@ -1892,8 +1899,10 @@ del_mcast_entry(struct ctl_context *ctx,
>              vteprec_mcast_macs_remote_delete(mcast_mac->remote_cfg);
>          }
>
> -        free(node->data);
> -        shash_delete(mcast_shash, node);
> +        if (node) {
> +            free(node->data);
> +            shash_delete(mcast_shash, node);
> +        }
>      } else {
>          if (local) {
>              vteprec_mcast_macs_local_set_locator_set(mcast_mac->local_cfg,
> -- 
> 2.39.2
>
> _______________________________________________
> dev mailing list
> [email protected]
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to