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