]> git.puffer.fish Git - mirror/frr.git/commitdiff
isisd: Don't set subtlv structure if we didn't unpack any subtlvs 4272/head
authorChristian Franke <chris@opensourcerouting.org>
Fri, 10 May 2019 11:24:38 +0000 (13:24 +0200)
committerChristian Franke <chris@opensourcerouting.org>
Fri, 10 May 2019 11:24:38 +0000 (13:24 +0200)
This ensures deserialized and serialized TLV representation is
consistent.

isisd/isis_tlvs.c
tests/isisd/test_fuzz_isis_tlv_tests.h.gz

index f72540b81109004d5490717292e4bbf23fe74d68..ae149a04284cd0cb6b8440fa13d49c82c5d17fd1 100644 (file)
@@ -405,7 +405,7 @@ static int pack_subtlvs(struct isis_subtlvs *subtlvs, struct stream *s)
 
 static int unpack_tlvs(enum isis_tlv_context context, size_t avail_len,
                       struct stream *stream, struct sbuf *log, void *dest,
-                      int indent);
+                      int indent, bool *unpacked_known_tlvs);
 
 /* Functions related to TLVs 1 Area Addresses */
 
@@ -796,7 +796,7 @@ static int unpack_item_extended_reach(uint16_t mtid, uint8_t len,
                size_t subtlv_start = stream_get_getp(s);
 
                if (unpack_tlvs(ISIS_CONTEXT_SUBTLV_NE_REACH, subtlv_len, s,
-                               log, NULL, indent + 4)) {
+                               log, NULL, indent + 4, NULL)) {
                        goto out;
                }
 
@@ -1391,10 +1391,16 @@ static int unpack_item_extended_ip_reach(uint16_t mtid, uint8_t len,
                }
 
                rv->subtlvs = isis_alloc_subtlvs(ISIS_CONTEXT_SUBTLV_IP_REACH);
+               bool unpacked_known_tlvs = false;
+
                if (unpack_tlvs(ISIS_CONTEXT_SUBTLV_IP_REACH, subtlv_len, s,
-                               log, rv->subtlvs, indent + 4)) {
+                               log, rv->subtlvs, indent + 4, &unpacked_known_tlvs)) {
                        goto out;
                }
+               if (!unpacked_known_tlvs) {
+                       isis_free_subtlvs(rv->subtlvs);
+                       rv->subtlvs = NULL;
+               }
        }
 
        append_item(items, (struct isis_item *)rv);
@@ -1870,10 +1876,16 @@ static int unpack_item_ipv6_reach(uint16_t mtid, uint8_t len, struct stream *s,
                }
 
                rv->subtlvs = isis_alloc_subtlvs(ISIS_CONTEXT_SUBTLV_IPV6_REACH);
+               bool unpacked_known_tlvs = false;
+
                if (unpack_tlvs(ISIS_CONTEXT_SUBTLV_IPV6_REACH, subtlv_len, s,
-                               log, rv->subtlvs, indent + 4)) {
+                               log, rv->subtlvs, indent + 4, &unpacked_known_tlvs)) {
                        goto out;
                }
+               if (!unpacked_known_tlvs) {
+                       isis_free_subtlvs(rv->subtlvs);
+                       rv->subtlvs = NULL;
+               }
        }
 
        append_item(items, (struct isis_item *)rv);
@@ -2971,7 +2983,7 @@ static int unpack_tlv_unknown(enum isis_tlv_context context, uint8_t tlv_type,
 
 static int unpack_tlv(enum isis_tlv_context context, size_t avail_len,
                      struct stream *stream, struct sbuf *log, void *dest,
-                     int indent)
+                     int indent, bool *unpacked_known_tlvs)
 {
        uint8_t tlv_type, tlv_len;
        const struct tlv_ops *ops;
@@ -3002,6 +3014,8 @@ static int unpack_tlv(enum isis_tlv_context context, size_t avail_len,
 
        ops = tlv_table[context][tlv_type];
        if (ops && ops->unpack) {
+               if (unpacked_known_tlvs)
+                       *unpacked_known_tlvs = true;
                return ops->unpack(context, tlv_type, tlv_len, stream, log,
                                   dest, indent + 2);
        }
@@ -3012,7 +3026,7 @@ static int unpack_tlv(enum isis_tlv_context context, size_t avail_len,
 
 static int unpack_tlvs(enum isis_tlv_context context, size_t avail_len,
                       struct stream *stream, struct sbuf *log, void *dest,
-                      int indent)
+                      int indent, bool *unpacked_known_tlvs)
 {
        int rv;
        size_t tlv_start, tlv_pos;
@@ -3025,7 +3039,7 @@ static int unpack_tlvs(enum isis_tlv_context context, size_t avail_len,
 
        while (tlv_pos < avail_len) {
                rv = unpack_tlv(context, avail_len - tlv_pos, stream, log, dest,
-                               indent + 2);
+                               indent + 2, unpacked_known_tlvs);
                if (rv)
                        return rv;
 
@@ -3057,7 +3071,7 @@ int isis_unpack_tlvs(size_t avail_len, struct stream *stream,
 
        result = isis_alloc_tlvs();
        rv = unpack_tlvs(ISIS_CONTEXT_LSP, avail_len, stream, &logbuf, result,
-                        indent);
+                        indent, NULL);
 
        *log = sbuf_buf(&logbuf);
        *dest = result;
index 4a89bda84eac865059ab1755ffddc96497bc9691..6f8bc2218e2f7bcca388a9f7185bcb2816223ca9 100644 (file)
Binary files a/tests/isisd/test_fuzz_isis_tlv_tests.h.gz and b/tests/isisd/test_fuzz_isis_tlv_tests.h.gz differ