Exemple #1
0
TEST_END

TEST_BEGIN(test_malloc_strtoumax_no_endptr)
{
	int err;

	set_errno(0);
	assert_ju_eq(malloc_strtoumax("0", NULL, 0), 0, "Unexpected result");
	err = get_errno();
	assert_d_eq(err, 0, "Unexpected failure");
}
Exemple #2
0
TEST_END

TEST_BEGIN(test_malloc_strtoumax)
{
	struct test_s {
		const char *input;
		const char *expected_remainder;
		int base;
		int expected_errno;
		const char *expected_errno_name;
		uintmax_t expected_x;
	};
#define	ERR(e)	e, #e
#define	UMAX(x)	((uintmax_t)x##ULL)
	struct test_s tests[] = {
		{"0",		"0",	-1,	ERR(EINVAL),	UINTMAX_MAX},
		{"0",		"0",	1,	ERR(EINVAL),	UINTMAX_MAX},
		{"0",		"0",	37,	ERR(EINVAL),	UINTMAX_MAX},

		{"",		"",	0,	ERR(EINVAL),	UINTMAX_MAX},
		{"+",		"+",	0,	ERR(EINVAL),	UINTMAX_MAX},
		{"++3",		"++3",	0,	ERR(EINVAL),	UINTMAX_MAX},
		{"-",		"-",	0,	ERR(EINVAL),	UINTMAX_MAX},

		{"42",		"",	0,	ERR(0),		UMAX(42)},
		{"+42",		"",	0,	ERR(0),		UMAX(42)},
		{"-42",		"",	0,	ERR(0),		UMAX(-42)},
		{"042",		"",	0,	ERR(0),		UMAX(042)},
		{"+042",	"",	0,	ERR(0),		UMAX(042)},
		{"-042",	"",	0,	ERR(0),		UMAX(-042)},
		{"0x42",	"",	0,	ERR(0),		UMAX(0x42)},
		{"+0x42",	"",	0,	ERR(0),		UMAX(0x42)},
		{"-0x42",	"",	0,	ERR(0),		UMAX(-0x42)},

		{"0",		"",	0,	ERR(0),		UMAX(0)},
		{"1",		"",	0,	ERR(0),		UMAX(1)},

		{"42",		"",	0,	ERR(0),		UMAX(42)},
		{" 42",		"",	0,	ERR(0),		UMAX(42)},
		{"42 ",		" ",	0,	ERR(0),		UMAX(42)},
		{"0x",		"x",	0,	ERR(0),		UMAX(0)},
		{"42x",		"x",	0,	ERR(0),		UMAX(42)},

		{"07",		"",	0,	ERR(0),		UMAX(7)},
		{"010",		"",	0,	ERR(0),		UMAX(8)},
		{"08",		"8",	0,	ERR(0),		UMAX(0)},
		{"0_",		"_",	0,	ERR(0),		UMAX(0)},

		{"0x",		"x",	0,	ERR(0),		UMAX(0)},
		{"0X",		"X",	0,	ERR(0),		UMAX(0)},
		{"0xg",		"xg",	0,	ERR(0),		UMAX(0)},
		{"0XA",		"",	0,	ERR(0),		UMAX(10)},

		{"010",		"",	10,	ERR(0),		UMAX(10)},
		{"0x3",		"x3",	10,	ERR(0),		UMAX(0)},

		{"12",		"2",	2,	ERR(0),		UMAX(1)},
		{"78",		"8",	8,	ERR(0),		UMAX(7)},
		{"9a",		"a",	10,	ERR(0),		UMAX(9)},
		{"9A",		"A",	10,	ERR(0),		UMAX(9)},
		{"fg",		"g",	16,	ERR(0),		UMAX(15)},
		{"FG",		"G",	16,	ERR(0),		UMAX(15)},
		{"0xfg",	"g",	16,	ERR(0),		UMAX(15)},
		{"0XFG",	"G",	16,	ERR(0),		UMAX(15)},
		{"z_",		"_",	36,	ERR(0),		UMAX(35)},
		{"Z_",		"_",	36,	ERR(0),		UMAX(35)}
	};
#undef ERR
#undef UMAX
	unsigned i;

	for (i = 0; i < sizeof(tests)/sizeof(struct test_s); i++) {
		struct test_s *test = &tests[i];
		int err;
		uintmax_t result;
		char *remainder;

		set_errno(0);
		result = malloc_strtoumax(test->input, &remainder, test->base);
		err = get_errno();
		assert_d_eq(err, test->expected_errno,
		    "Expected errno %s for \"%s\", base %d",
		    test->expected_errno_name, test->input, test->base);
		assert_str_eq(remainder, test->expected_remainder,
		    "Unexpected remainder for \"%s\", base %d",
		    test->input, test->base);
		if (err == 0) {
			assert_ju_eq(result, test->expected_x,
			    "Unexpected result for \"%s\", base %d",
			    test->input, test->base);
		}
	}
}
Exemple #3
0
int
malloc_vsnprintf(char *str, size_t size, const char *format, va_list ap)
{
	int ret;
	size_t i;
	const char *f;

#define	APPEND_C(c) do {						\
	if (i < size)							\
		str[i] = (c);						\
	i++;								\
} while (0)
#define	APPEND_S(s, slen) do {						\
	if (i < size) {							\
		size_t cpylen = (slen <= size - i) ? slen : size - i;	\
		memcpy(&str[i], s, cpylen);				\
	}								\
	i += slen;							\
} while (0)
#define	APPEND_PADDED_S(s, slen, width, left_justify) do {		\
	/* Left padding. */						\
	size_t pad_len = (width == -1) ? 0 : ((slen < (size_t)width) ?	\
	    (size_t)width - slen : 0);					\
	if (left_justify == false && pad_len != 0) {			\
		size_t j;						\
		for (j = 0; j < pad_len; j++)				\
			APPEND_C(' ');					\
	}								\
	/* Value. */							\
	APPEND_S(s, slen);						\
	/* Right padding. */						\
	if (left_justify && pad_len != 0) {				\
		size_t j;						\
		for (j = 0; j < pad_len; j++)				\
			APPEND_C(' ');					\
	}								\
} while (0)
#define GET_ARG_NUMERIC(val, len) do {					\
	switch (len) {							\
	case '?':							\
		val = va_arg(ap, int);					\
		break;							\
	case '?' | 0x80:						\
		val = va_arg(ap, unsigned int);				\
		break;							\
	case 'l':							\
		val = va_arg(ap, long);					\
		break;							\
	case 'l' | 0x80:						\
		val = va_arg(ap, unsigned long);			\
		break;							\
	case 'q':							\
		val = va_arg(ap, long long);				\
		break;							\
	case 'q' | 0x80:						\
		val = va_arg(ap, unsigned long long);			\
		break;							\
	case 'j':							\
		val = va_arg(ap, intmax_t);				\
		break;							\
	case 't':							\
		val = va_arg(ap, ptrdiff_t);				\
		break;							\
	case 'z':							\
		val = va_arg(ap, ssize_t);				\
		break;							\
	case 'z' | 0x80:						\
		val = va_arg(ap, size_t);				\
		break;							\
	case 'p': /* Synthetic; used for %p. */				\
		val = va_arg(ap, uintptr_t);				\
		break;							\
	default: not_reached();						\
	}								\
} while (0)

	i = 0;
	f = format;
	while (true) {
		switch (*f) {
		case '\0': goto label_out;
		case '%': {
			bool alt_form = false;
			bool zero_pad = false;
			bool left_justify = false;
			bool plus_space = false;
			bool plus_plus = false;
			int prec = -1;
			int width = -1;
			unsigned char len = '?';

			f++;
			if (*f == '%') {
				/* %% */
				APPEND_C(*f);
				break;
			}
			/* Flags. */
			while (true) {
				switch (*f) {
				case '#':
					assert(alt_form == false);
					alt_form = true;
					break;
				case '0':
					assert(zero_pad == false);
					zero_pad = true;
					break;
				case '-':
					assert(left_justify == false);
					left_justify = true;
					break;
				case ' ':
					assert(plus_space == false);
					plus_space = true;
					break;
				case '+':
					assert(plus_plus == false);
					plus_plus = true;
					break;
				default: goto label_width;
				}
				f++;
			}
			/* Width. */
			label_width:
			switch (*f) {
			case '*':
				width = va_arg(ap, int);
				f++;
				break;
			case '0': case '1': case '2': case '3': case '4':
			case '5': case '6': case '7': case '8': case '9': {
				uintmax_t uwidth;
				set_errno(0);
				uwidth = malloc_strtoumax(f, (char **)&f, 10);
				assert(uwidth != UINTMAX_MAX || get_errno() !=
				    ERANGE);
				width = (int)uwidth;
				if (*f == '.') {
					f++;
					goto label_precision;
				} else
					goto label_length;
				break;
			} case '.':
				f++;
				goto label_precision;
			default: goto label_length;
			}
			/* Precision. */
			label_precision:
			switch (*f) {
			case '*':
				prec = va_arg(ap, int);
				f++;
				break;
			case '0': case '1': case '2': case '3': case '4':
			case '5': case '6': case '7': case '8': case '9': {
				uintmax_t uprec;
				set_errno(0);
				uprec = malloc_strtoumax(f, (char **)&f, 10);
				assert(uprec != UINTMAX_MAX || get_errno() !=
				    ERANGE);
				prec = (int)uprec;
				break;
			}
			default: break;
			}
			/* Length. */
			label_length:
			switch (*f) {
			case 'l':
				f++;
				if (*f == 'l') {
					len = 'q';
					f++;
				} else
					len = 'l';
				break;
			case 'j':
				len = 'j';
				f++;
				break;
			case 't':
				len = 't';
				f++;
				break;
			case 'z':
				len = 'z';
				f++;
				break;
			default: break;
			}
			/* Conversion specifier. */
			switch (*f) {
				char *s;
				size_t slen;
			case 'd': case 'i': {
				intmax_t val JEMALLOC_CC_SILENCE_INIT(0);
				char buf[D2S_BUFSIZE];

				GET_ARG_NUMERIC(val, len);
				s = d2s(val, (plus_plus ? '+' : (plus_space ?
				    ' ' : '-')), buf, &slen);
				APPEND_PADDED_S(s, slen, width, left_justify);
				f++;
				break;
			} case 'o': {
				uintmax_t val JEMALLOC_CC_SILENCE_INIT(0);
				char buf[O2S_BUFSIZE];

				GET_ARG_NUMERIC(val, len | 0x80);
				s = o2s(val, alt_form, buf, &slen);
				APPEND_PADDED_S(s, slen, width, left_justify);
				f++;
				break;
			} case 'u': {
				uintmax_t val JEMALLOC_CC_SILENCE_INIT(0);
				char buf[U2S_BUFSIZE];

				GET_ARG_NUMERIC(val, len | 0x80);
				s = u2s(val, 10, false, buf, &slen);
				APPEND_PADDED_S(s, slen, width, left_justify);
				f++;
				break;
			} case 'x': case 'X': {
				uintmax_t val JEMALLOC_CC_SILENCE_INIT(0);
				char buf[X2S_BUFSIZE];

				GET_ARG_NUMERIC(val, len | 0x80);
				s = x2s(val, alt_form, *f == 'X', buf, &slen);
				APPEND_PADDED_S(s, slen, width, left_justify);
				f++;
				break;
			} case 'c': {
				unsigned char val;
				char buf[2];

				assert(len == '?' || len == 'l');
				assert_not_implemented(len != 'l');
				val = va_arg(ap, int);
				buf[0] = val;
				buf[1] = '\0';
				APPEND_PADDED_S(buf, 1, width, left_justify);
				f++;
				break;
			} case 's':
				assert(len == '?' || len == 'l');
				assert_not_implemented(len != 'l');
				s = va_arg(ap, char *);
				slen = (prec == -1) ? strlen(s) : prec;
				APPEND_PADDED_S(s, slen, width, left_justify);
				f++;
				break;
			case 'p': {
				uintmax_t val;
				char buf[X2S_BUFSIZE];

				GET_ARG_NUMERIC(val, 'p');
				s = x2s(val, true, false, buf, &slen);
				APPEND_PADDED_S(s, slen, width, left_justify);
				f++;
				break;
			}
			default: not_implemented();
			}
			break;
		} default: {
			APPEND_C(*f);
			f++;
			break;
		}}
	}
	label_out:
	if (i < size)
		str[i] = '\0';
	else
		str[size - 1] = '\0';
	ret = i;

#undef APPEND_C
#undef APPEND_S
#undef APPEND_PADDED_S
#undef GET_ARG_NUMERIC
	return (ret);
}
Exemple #4
0
static int
ctl_lookup(const char *name, ctl_node_t const **nodesp, size_t *mibp,
    size_t *depthp)
{
	int ret;
	const char *elm, *tdot, *dot;
	size_t elen, i, j;
	const ctl_named_node_t *node;

	elm = name;
	/* Equivalent to strchrnul(). */
	dot = ((tdot = strchr(elm, '.')) != NULL) ? tdot : strchr(elm, '\0');
	elen = (size_t)((uintptr_t)dot - (uintptr_t)elm);
	if (elen == 0) {
		ret = ENOENT;
		goto label_return;
	}
	node = super_root_node;
	for (i = 0; i < *depthp; i++) {
		assert(node);
		assert(node->nchildren > 0);
		if (ctl_named_node(node->children) != NULL) {
			const ctl_named_node_t *pnode = node;

			/* Children are named. */
			for (j = 0; j < node->nchildren; j++) {
				const ctl_named_node_t *child =
				    ctl_named_children(node, j);
				if (strlen(child->name) == elen &&
				    strncmp(elm, child->name, elen) == 0) {
					node = child;
					if (nodesp != NULL)
						nodesp[i] =
						    (const ctl_node_t *)node;
					mibp[i] = j;
					break;
				}
			}
			if (node == pnode) {
				ret = ENOENT;
				goto label_return;
			}
		} else {
			uintmax_t index;
			const ctl_indexed_node_t *inode;

			/* Children are indexed. */
			index = malloc_strtoumax(elm, NULL, 10);
			if (index == UINTMAX_MAX || index > SIZE_T_MAX) {
				ret = ENOENT;
				goto label_return;
			}

			inode = ctl_indexed_node(node->children);
			node = inode->index(mibp, *depthp, (size_t)index);
			if (node == NULL) {
				ret = ENOENT;
				goto label_return;
			}

			if (nodesp != NULL)
				nodesp[i] = (const ctl_node_t *)node;
			mibp[i] = (size_t)index;
		}

		if (node->ctl != NULL) {
			/* Terminal node. */
			if (*dot != '\0') {
				/*
				 * The name contains more elements than are
				 * in this path through the tree.
				 */
				ret = ENOENT;
				goto label_return;
			}
			/* Complete lookup successful. */
			*depthp = i + 1;
			break;
		}

		/* Update elm. */
		if (*dot == '\0') {
			/* No more elements. */
			ret = ENOENT;
			goto label_return;
		}
		elm = &dot[1];
		dot = ((tdot = strchr(elm, '.')) != NULL) ? tdot :
		    strchr(elm, '\0');
		elen = (size_t)((uintptr_t)dot - (uintptr_t)elm);
	}

	ret = 0;
label_return:
	return (ret);
}