]> git.proxmox.com Git - mirror_frr.git/blob - tests/isisd/test_fuzz_isis_tlv.c
*: list_delete_and_null() -> list_delete()
[mirror_frr.git] / tests / isisd / test_fuzz_isis_tlv.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include "test_fuzz_isis_tlv_tests.h"
6
7 #include <zebra.h>
8
9 #include "memory.h"
10 #include "sbuf.h"
11 #include "stream.h"
12 #include "thread.h"
13
14 #include "isisd/isis_circuit.h"
15 #include "isisd/isis_tlvs.h"
16
17 #define TEST_STREAM_SIZE 1500
18
19 struct thread_master *master;
20 int isis_sock_init(struct isis_circuit *circuit);
21 int isis_sock_init(struct isis_circuit *circuit)
22 {
23 return 0;
24 }
25
26 struct zebra_privs_t isisd_privs;
27
28 static bool atexit_registered;
29
30 static void show_meminfo_at_exit(void)
31 {
32 log_memstats(stderr, "isis fuzztest");
33 }
34
35 static int comp_line(const void *p1, const void *p2)
36 {
37 return strcmp(*(char * const *)p1, *(char * const *)p2);
38 }
39
40 static char *sortlines(char *in)
41 {
42 size_t line_count = 1;
43 size_t rv_len = strlen(in) + 1;
44 size_t rv_pos = 0;
45 char *rv = XMALLOC(MTYPE_TMP, rv_len);
46
47 for (char *c = in; *c; c++) {
48 if (*c == '\n')
49 line_count++;
50 }
51
52 if (line_count == 1) {
53 strncpy(rv, in, rv_len);
54 return rv;
55 }
56
57 char **lines = XCALLOC(MTYPE_TMP, sizeof(char *)*line_count);
58 char *saveptr = NULL;
59 size_t i = 0;
60
61 for (char *line = strtok_r(in, "\n", &saveptr); line;
62 line = strtok_r(NULL, "\n", &saveptr)) {
63 lines[i++] = line;
64 assert(i <= line_count);
65 }
66
67 line_count = i;
68
69 qsort(lines, line_count, sizeof(char *), comp_line);
70
71 for (i = 0; i < line_count; i++) {
72 int printf_rv = snprintf(rv + rv_pos, rv_len - rv_pos, "%s\n", lines[i]);
73 assert(printf_rv >= 0);
74 rv_pos += printf_rv;
75 }
76
77 XFREE(MTYPE_TMP, lines);
78 return rv;
79 }
80
81 static int test(FILE *input, FILE *output)
82 {
83 struct stream *s = stream_new(TEST_STREAM_SIZE);
84 char buf[TEST_STREAM_SIZE];
85 size_t bytes_read = 0;
86
87 if (!atexit_registered) {
88 atexit(show_meminfo_at_exit);
89 atexit_registered = true;
90 }
91
92 while (STREAM_WRITEABLE(s) && !feof(input)) {
93 bytes_read = fread(buf, 1, STREAM_WRITEABLE(s), input);
94 if (bytes_read == 0)
95 break;
96 stream_put(s, buf, bytes_read);
97 }
98
99 if (bytes_read && !feof(input)) {
100 fprintf(output, "Too much input data.\n");
101 stream_free(s);
102 return 1;
103 }
104
105 stream_set_getp(s, 0);
106 struct isis_tlvs *tlvs;
107 const char *log;
108 int rv = isis_unpack_tlvs(STREAM_READABLE(s), s, &tlvs, &log);
109
110 if (rv) {
111 fprintf(output, "Could not unpack TLVs:\n%s\n", log);
112 isis_free_tlvs(tlvs);
113 stream_free(s);
114 return 2;
115 }
116
117 fprintf(output, "Unpack log:\n%s", log);
118 const char *s_tlvs = isis_format_tlvs(tlvs);
119 fprintf(output, "Unpacked TLVs:\n%s", s_tlvs);
120
121 struct isis_item *orig_auth = tlvs->isis_auth.head;
122 tlvs->isis_auth.head = NULL;
123 s_tlvs = isis_format_tlvs(tlvs);
124 struct isis_tlvs *tlv_copy = isis_copy_tlvs(tlvs);
125 tlvs->isis_auth.head = orig_auth;
126 isis_free_tlvs(tlvs);
127
128 struct stream *s2 = stream_new(TEST_STREAM_SIZE);
129
130 if (isis_pack_tlvs(tlv_copy, s2, (size_t)-1, false, false)) {
131 fprintf(output, "Could not pack TLVs.\n");
132 assert(0);
133 }
134
135 stream_set_getp(s2, 0);
136 rv = isis_unpack_tlvs(STREAM_READABLE(s2), s2, &tlvs, &log);
137 if (rv) {
138 fprintf(output, "Could not unpack own TLVs:\n%s\n", log);
139 assert(0);
140 }
141
142 char *orig_tlvs = XSTRDUP(MTYPE_TMP, s_tlvs);
143 s_tlvs = isis_format_tlvs(tlvs);
144
145 if (strcmp(orig_tlvs, s_tlvs)) {
146 fprintf(output,
147 "Deserialized and Serialized LSP seem to differ.\n");
148 fprintf(output, "Re-Unpacked TLVs:\n%s", s_tlvs);
149 assert(0);
150 }
151
152 isis_free_tlvs(tlv_copy);
153 stream_free(s);
154 stream_free(s2);
155
156 struct list *fragments = isis_fragment_tlvs(tlvs, 550);
157 isis_free_tlvs(tlvs);
158 if (!fragments) {
159 XFREE(MTYPE_TMP, orig_tlvs);
160 return 0;
161 }
162
163 s = stream_new(550);
164
165 struct sbuf fragment_format;
166 sbuf_init(&fragment_format, NULL, 0);
167
168 struct listnode *node;
169 for (ALL_LIST_ELEMENTS_RO(fragments, node, tlvs)) {
170 stream_reset(s);
171 int rv = isis_pack_tlvs(tlvs, s, (size_t)-1, false, false);
172 if (rv) {
173 fprintf(output, "Could not pack fragment, too large.\n");
174 assert(0);
175 }
176 sbuf_push(&fragment_format, 0, "%s", isis_format_tlvs(tlvs));
177 isis_free_tlvs(tlvs);
178 }
179 list_delete(&fragments);
180 stream_free(s);
181
182 char *fragment_content = sortlines((char *)sbuf_buf(&fragment_format));
183 sbuf_free(&fragment_format);
184 char *orig_tlv_content = sortlines(orig_tlvs);
185 XFREE(MTYPE_TMP, orig_tlvs);
186
187 if (strcmp(fragment_content, orig_tlv_content)) {
188 fprintf(output, "Fragmented and unfragmented LSP seem to differ.\n");
189 fprintf(output, "Original:\n%s\nFragmented:\n%s\n",
190 orig_tlv_content, fragment_content);
191 assert(0);
192 }
193
194 XFREE(MTYPE_TMP, fragment_content);
195 XFREE(MTYPE_TMP, orig_tlv_content);
196
197 return 0;
198 }