⬢ DragonFlyBSD Kernel Audit
DF-5755 / difftest.c
← back to finding ↓ download raw
/* DF-5755/DF-5756 — userland iconv(3) differential.
 *
 * The kernel's libiconv UCS converter accepts/rejects the same byte
 * sequences differently from the base-system userland iconv(3).  This tool
 * prints, for each case, what userland does — the contrast baseline for the
 * kernel witness module and msdosfs runs.
 */
#include <err.h>
#include <iconv.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

struct tc {
	const char *tag;
	const char *to, *from;
	const char *in;
	size_t inlen;
};

static struct tc cases[] = {
	{ "u8_overlong_slash_C0AF",  "UTF-16BE", "UTF-8",   "\xC0\xAF", 2 },
	{ "u8_overlong3_slash_E080AF","UTF-16BE","UTF-8",   "\xE0\x80\xAF", 3 },
	{ "u8_overlong4_F08FBFBF",   "UTF-16BE", "UTF-8",   "\xF0\x8F\xBF\xBF", 4 },
	{ "u8_valid_slash",          "UTF-16BE", "UTF-8",   "\x2F", 1 },
	{ "u16_lone_low_DC00",       "UTF-8",    "UTF-16BE","\xDC\x00", 2 },
	{ "u16_lone_high_D83D",      "UTF-8",    "UTF-16BE","\xD8\x3D", 2 },
	{ "u16_valid_pair_D83DDE48", "UTF-8",    "UTF-16BE","\xD8\x3D\xDE\x48", 4 },
	{ NULL, NULL, NULL, NULL, 0 }
};

int
main(void)
{
	int i;

	for (i = 0; cases[i].tag; i++) {
		iconv_t cd;
		char out[16];
		const char *src;
		char *dst;
		size_t il, ol, k;

		errno = 0;
		cd = iconv_open(cases[i].to, cases[i].from);
		if (cd == (iconv_t)-1) {
			printf("%-28s : iconv_open(%s,%s) FAILED: %s\n",
			    cases[i].tag, cases[i].to, cases[i].from,
			    strerror(errno));
			continue;
		}
		memset(out, 0xAA, sizeof(out));
		src = cases[i].in;
		dst = out;
		il = cases[i].inlen;
		ol = sizeof(out);
		errno = 0;
		iconv(cd, &src, &il, &dst, &ol);
		printf("%-28s : ret-errno=%s consumed=%zu out=",
		    cases[i].tag, errno ? strerror(errno) : "0(OK)",
		    cases[i].inlen - il);
		for (k = 0; k < sizeof(out) - ol; k++)
			printf("%02x ", (unsigned char)out[k]);
		printf("\n");
		iconv_close(cd);
	}
	return 0;
}