libo 0.1 released

| Comments

Just tagged libo 0.1, a library for fast integer overflow detection.

The major interface change in this version is that instead of writing smulo32(...) for detecting signed 32-bit multiplication overflow, you just call overflow_mul(...), and it will figure out the type for you (using black magic).

I have also added a unit test using Google Test. It would be great if you can help generate and test ARM/PowerPC implementations.

To give you a sense of how efficient libo is, below is libo’s implementation of overflow_mul() for long on x86_64:

1
2
3
4
5
overflow_mul_l:
	imulq	%rdx, %rsi
	movq	%rsi, (%rdi)
	seto	%al
	ret

on ppc:

1
2
3
4
5
6
7
8
9
overflow_mul_l:
	mullw 6, 4, 5
	stw 6, 0(3)
	mulhw 3, 4, 5
	srawi 4, 6, 31
	xor 3, 3, 4
	addic 4, 3, -1
	subfe 3, 4, 3
	blr

For a comparison, this is the implementation from CERT’s IntegerLib.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#if (LLONG_MAX >= 2*LONG_MAX)
signed long multsl(signed  long lhs, signed  long rhs){
	signed long long tmp = (signed long long)lhs * (signed long long)rhs;
	errno = 0;
	if ( (tmp > LONG_MAX) || (tmp < LONG_MIN)){
		error_handler("OVERFLOW ERROR", NULL, EOVERFLOW);
		errno = EINVAL;
	}
	return (signed long)tmp;
}
#else
signed long multsl(signed long lhs, signed long rhs){
	errno = 0;
	if ( (lhs == 0) || (rhs == 0)) return 0;
	if( lhs > 0){
		if( rhs > 0){
			if(lhs > (LONG_MAX / rhs)){
				error_handler("OVERFLOW ERROR", NULL, EOVERFLOW);
				errno = EINVAL;
			}
		} else {
			if ( rhs < (LONG_MIN / lhs)){
				error_handler("OVERFLOW ERROR", NULL, EOVERFLOW);
				errno = EINVAL;
			}
		}
	} else {
		if(rhs > 0){
			if( lhs < (LONG_MIN / rhs)){
				error_handler("OVERFLOW ERROR", NULL, EOVERFLOW);
				errno = EINVAL;
			}
		} else {
			if( (lhs != 0) && (rhs < (LONG_MAX / lhs))){
				error_handler("OVERFLOW ERROR", NULL, EOVERFLOW);
				errno = EINVAL;
			}
		}
	}

	return lhs * rhs;
}
#endif /* LLONG_MAX >= 2*LONG_MAX */

Comments