mirror of
				https://git.proxmox.com/git/mirror_frr
				synced 2025-11-04 06:38:04 +00:00 
			
		
		
		
	We should probably prevent any type of namespace collision with something else. Signed-off-by: Donald Sharp <sharpd@nvidia.com>
		
			
				
	
	
		
			192 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			192 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
#ifdef HAVE_CONFIG_H
 | 
						|
#include "config.h"
 | 
						|
#endif
 | 
						|
 | 
						|
#include "test_fuzz_isis_tlv_tests.h"
 | 
						|
 | 
						|
#include <zebra.h>
 | 
						|
 | 
						|
#include "memory.h"
 | 
						|
#include "sbuf.h"
 | 
						|
#include "stream.h"
 | 
						|
#include "frrevent.h"
 | 
						|
 | 
						|
#include "isisd/isis_circuit.h"
 | 
						|
#include "isisd/isis_tlvs.h"
 | 
						|
 | 
						|
#include "test_common.h"
 | 
						|
 | 
						|
#define TEST_STREAM_SIZE 1500
 | 
						|
 | 
						|
static bool atexit_registered;
 | 
						|
 | 
						|
static void show_meminfo_at_exit(void)
 | 
						|
{
 | 
						|
	log_memstats(stderr, "isis fuzztest");
 | 
						|
}
 | 
						|
 | 
						|
static int comp_line(const void *p1, const void *p2)
 | 
						|
{
 | 
						|
	return strcmp(*(char * const *)p1, *(char * const *)p2);
 | 
						|
}
 | 
						|
 | 
						|
static char *sortlines(char *in)
 | 
						|
{
 | 
						|
	size_t line_count = 1;
 | 
						|
	size_t rv_len = strlen(in) + 1;
 | 
						|
	size_t rv_pos = 0;
 | 
						|
	char *rv = XMALLOC(MTYPE_TMP, rv_len);
 | 
						|
 | 
						|
	for (char *c = in; *c; c++) {
 | 
						|
		if (*c == '\n')
 | 
						|
			line_count++;
 | 
						|
	}
 | 
						|
 | 
						|
	if (line_count == 1) {
 | 
						|
		strncpy(rv, in, rv_len);
 | 
						|
		return rv;
 | 
						|
	}
 | 
						|
 | 
						|
	char **lines = XCALLOC(MTYPE_TMP, sizeof(char *)*line_count);
 | 
						|
	char *saveptr = NULL;
 | 
						|
	size_t i = 0;
 | 
						|
 | 
						|
	for (char *line = strtok_r(in, "\n", &saveptr); line;
 | 
						|
	     line = strtok_r(NULL, "\n", &saveptr)) {
 | 
						|
		lines[i++] = line;
 | 
						|
		assert(i <= line_count);
 | 
						|
	}
 | 
						|
 | 
						|
	line_count = i;
 | 
						|
 | 
						|
	qsort(lines, line_count, sizeof(char *), comp_line);
 | 
						|
 | 
						|
	for (i = 0; i < line_count; i++) {
 | 
						|
		int printf_rv = snprintf(rv + rv_pos, rv_len - rv_pos, "%s\n", lines[i]);
 | 
						|
		assert(printf_rv >= 0);
 | 
						|
		rv_pos += printf_rv;
 | 
						|
	}
 | 
						|
 | 
						|
	XFREE(MTYPE_TMP, lines);
 | 
						|
	return rv;
 | 
						|
}
 | 
						|
 | 
						|
static int test(FILE *input, FILE *output)
 | 
						|
{
 | 
						|
	struct stream *s = stream_new(TEST_STREAM_SIZE);
 | 
						|
	char buf[TEST_STREAM_SIZE];
 | 
						|
	size_t bytes_read = 0;
 | 
						|
 | 
						|
	if (!atexit_registered) {
 | 
						|
		atexit(show_meminfo_at_exit);
 | 
						|
		atexit_registered = true;
 | 
						|
	}
 | 
						|
 | 
						|
	while (STREAM_WRITEABLE(s) && !feof(input)) {
 | 
						|
		bytes_read = fread(buf, 1, STREAM_WRITEABLE(s), input);
 | 
						|
		if (bytes_read == 0)
 | 
						|
			break;
 | 
						|
		stream_put(s, buf, bytes_read);
 | 
						|
	}
 | 
						|
 | 
						|
	if (bytes_read && !feof(input)) {
 | 
						|
		fprintf(output, "Too much input data.\n");
 | 
						|
		stream_free(s);
 | 
						|
		return 1;
 | 
						|
	}
 | 
						|
 | 
						|
	stream_set_getp(s, 0);
 | 
						|
	struct isis_tlvs *tlvs;
 | 
						|
	const char *log;
 | 
						|
	int rv = isis_unpack_tlvs(STREAM_READABLE(s), s, &tlvs, &log);
 | 
						|
 | 
						|
	if (rv) {
 | 
						|
		fprintf(output, "Could not unpack TLVs:\n%s\n", log);
 | 
						|
		isis_free_tlvs(tlvs);
 | 
						|
		stream_free(s);
 | 
						|
		return 2;
 | 
						|
	}
 | 
						|
 | 
						|
	fprintf(output, "Unpack log:\n%s", log);
 | 
						|
	const char *s_tlvs = isis_format_tlvs(tlvs, NULL);
 | 
						|
	fprintf(output, "Unpacked TLVs:\n%s", s_tlvs);
 | 
						|
 | 
						|
	struct isis_item *orig_auth = tlvs->isis_auth.head;
 | 
						|
	tlvs->isis_auth.head = NULL;
 | 
						|
	s_tlvs = isis_format_tlvs(tlvs, NULL);
 | 
						|
	struct isis_tlvs *tlv_copy = isis_copy_tlvs(tlvs);
 | 
						|
	tlvs->isis_auth.head = orig_auth;
 | 
						|
	isis_free_tlvs(tlvs);
 | 
						|
 | 
						|
	struct stream *s2 = stream_new(TEST_STREAM_SIZE);
 | 
						|
 | 
						|
	if (isis_pack_tlvs(tlv_copy, s2, (size_t)-1, false, false)) {
 | 
						|
		fprintf(output, "Could not pack TLVs.\n");
 | 
						|
		assert(0);
 | 
						|
	}
 | 
						|
 | 
						|
	stream_set_getp(s2, 0);
 | 
						|
	rv = isis_unpack_tlvs(STREAM_READABLE(s2), s2, &tlvs, &log);
 | 
						|
	if (rv) {
 | 
						|
		fprintf(output, "Could not unpack own TLVs:\n%s\n", log);
 | 
						|
		assert(0);
 | 
						|
	}
 | 
						|
 | 
						|
	char *orig_tlvs = XSTRDUP(MTYPE_TMP, s_tlvs);
 | 
						|
	s_tlvs = isis_format_tlvs(tlvs, NULL);
 | 
						|
 | 
						|
	if (strcmp(orig_tlvs, s_tlvs)) {
 | 
						|
		fprintf(output,
 | 
						|
			"Deserialized and Serialized LSP seem to differ.\n");
 | 
						|
		fprintf(output, "Re-Unpacked TLVs:\n%s", s_tlvs);
 | 
						|
		assert(0);
 | 
						|
	}
 | 
						|
 | 
						|
	isis_free_tlvs(tlv_copy);
 | 
						|
	stream_free(s);
 | 
						|
	stream_free(s2);
 | 
						|
 | 
						|
	struct list *fragments = isis_fragment_tlvs(tlvs, 550);
 | 
						|
	isis_free_tlvs(tlvs);
 | 
						|
	if (!fragments) {
 | 
						|
		XFREE(MTYPE_TMP, orig_tlvs);
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
 | 
						|
	s = stream_new(550);
 | 
						|
 | 
						|
	struct sbuf fragment_format;
 | 
						|
	sbuf_init(&fragment_format, NULL, 0);
 | 
						|
 | 
						|
	struct listnode *node;
 | 
						|
	for (ALL_LIST_ELEMENTS_RO(fragments, node, tlvs)) {
 | 
						|
		stream_reset(s);
 | 
						|
		int rv = isis_pack_tlvs(tlvs, s, (size_t)-1, false, false);
 | 
						|
		if (rv) {
 | 
						|
			fprintf(output, "Could not pack fragment, too large.\n");
 | 
						|
			assert(0);
 | 
						|
		}
 | 
						|
		sbuf_push(&fragment_format, 0, "%s", isis_format_tlvs(tlvs, NULL));
 | 
						|
		isis_free_tlvs(tlvs);
 | 
						|
	}
 | 
						|
	list_delete(&fragments);
 | 
						|
	stream_free(s);
 | 
						|
 | 
						|
	char *fragment_content = sortlines((char *)sbuf_buf(&fragment_format));
 | 
						|
	sbuf_free(&fragment_format);
 | 
						|
	char *orig_tlv_content = sortlines(orig_tlvs);
 | 
						|
	XFREE(MTYPE_TMP, orig_tlvs);
 | 
						|
 | 
						|
	if (strcmp(fragment_content, orig_tlv_content)) {
 | 
						|
		fprintf(output, "Fragmented and unfragmented LSP seem to differ.\n");
 | 
						|
		fprintf(output, "Original:\n%s\nFragmented:\n%s\n",
 | 
						|
			orig_tlv_content, fragment_content);
 | 
						|
		assert(0);
 | 
						|
	}
 | 
						|
 | 
						|
	XFREE(MTYPE_TMP, fragment_content);
 | 
						|
	XFREE(MTYPE_TMP, orig_tlv_content);
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 |