tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

<overflow.h> request for review



Hello,

I'm attaching a proposition of an overflow library,
as a part of the NetBSD kernel and libc with dedicated
header overflow.h.

The library was inspired by libo by Xi Wang:
https://github.com/xiw/libo

Xi Wang was kind to license his work to BSD.
I keep his license note as a credit even though
in the final work there is little code share.

The library was designed as a fast overflow checking
utilities, however in the final work I put the emphasis
on the safety rather then speed. A good compiler like
GCC/Clang will likely optimize the code for efficiency
on an architecture that is capable of it (like i386).

The library is intended to be used as a layer in libc
and kernel, everywhere an integer operation may overflow
in the * / + - operations.

Usage:
if (overflow_mul(&c, a, b))
    printf("overflow!\n");

The library is type agnostic, and for this there is need
for a C11 or GCC-compatible compiler. At the moment PCC
isn't supported.

There is fall-back with a dummy implementation, which
doesn't check for overflow, just does blindly a desired
arithmetic operation.

If the detection of overflows doesn't work and there is
used the dummy implementation there is  operations aren't
supported then OVERFLOW_FUNCS_DUMMY is defined.
A security important code should check for it (like calloc(3)),
and implement fallback for manual overflow checks.


I'm attaching test.c and test.sh (cc test.c -lutil)
for developer tests.

Known problems (at the moment I don't know how to fix):
1. '#include <overflow.h>' doesn't work, there is need
for '#include <sys/overflow.h>' how to fix it?
2. Sanity preprocessor magic
3. Missing libkern support (problems with overflow.c
not recognizing CHAR_MAX etc)

Please review,

After inclusion I will submit:
- ATF tests,
- strsuftoi/strsuftou replacement of strsuftoll(3)
- switch to these functions in calloc(3), reallocarray(3),
- everythin else.

CC: Christos and Joerg as you were helping me with
reallocarray(3).

Regards,

Attachment: patch-src-common
Description: Binary data

Attachment: patch-src-lib
Description: Binary data

Attachment: patch-src-sys
Description: Binary data

Attachment: patch-src-tools
Description: Binary data

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <err.h>
#include <stdint.h>
#include <inttypes.h>
#include <limits.h>
#include <util.h>

#include "overflow.h"

#define FUN(name,type,min,max, wrapped, print) \
void test_##name(char *a, char *b) \
{ \
	type v1 = wrapped(a, 0, min, max); \
	type v2 = wrapped(b, 0, min, max); \
\
	type res; \
	bool o; \
\
	o = overflow_add(&res, v1, v2); \
	printf("[%s] %" #print " + %" #print " = %" #print " [status %s]\n", #name , v1, v2, res, o ? "overflow" : "ok"); \
	o = overflow_sub(&res, v1, v2); \
	printf("[%s] %" #print " - %" #print " = %" #print " [status %s]\n", #name , v1, v2, res, o ? "overflow" : "ok"); \
	o = overflow_mul(&res, v1, v2); \
	printf("[%s] %" #print " * %" #print " = %" #print " [status %s]\n", #name , v1, v2, res, o ? "overflow" : "ok"); \
	o = overflow_div(&res, v1, v2); \
	printf("[%s] %" #print " / %" #print " = %" #print " [status %s]\n", #name , v1, v2, res, o ? "overflow" : "ok"); \
}

FUN(char,char,CHAR_MIN,CHAR_MAX,estrtoi, d)
FUN(schar,signed char,SCHAR_MIN,SCHAR_MAX,estrtoi, hhd)
FUN(uchar,unsigned char,0,UCHAR_MAX,estrtou, hhu)
FUN(shrt,short,SHRT_MIN,SHRT_MAX,estrtoi, hd)
FUN(ushrt,unsigned short,0,USHRT_MAX,estrtou, hu)
FUN(int,int,INT_MIN,INT_MAX,estrtoi, d)
FUN(uint,unsigned int,0,UINT_MAX,estrtou, u)
FUN(long,long,LONG_MIN,LONG_MAX,estrtoi, ld)
FUN(ulong,unsigned long,0,ULONG_MAX,estrtou, lu)
FUN(llong,long long,LLONG_MIN,LLONG_MAX,estrtoi, lld)
FUN(ullong,unsigned long long,0,ULLONG_MAX,estrtou, llu)

#define IF_CHECK(name) \
if (strcmp(argv[1], #name ) == 0) { \
	test_##name (argv[2], argv[3]); \
}

void usage(void)
{
	errx(EXIT_FAILURE, "usage: ./prog [char|schar|uchar|int|uint|long|ulong|llong|ullong] NUM1 NUM2");
}

int main(int argc, char **argv)
{
	if (argc < 4)
		usage();

	IF_CHECK(char)
	else IF_CHECK(schar)
	else IF_CHECK(uchar)
	else IF_CHECK(shrt)
	else IF_CHECK(ushrt)
	else IF_CHECK(int)
	else IF_CHECK(uint)
	else IF_CHECK(long)
	else IF_CHECK(ulong)
	else IF_CHECK(llong)
	else IF_CHECK(ullong)
	else usage();

	return 0;
}

Attachment: test.sh
Description: Unix shell archive



Home | Main Index | Thread Index | Old Index