On 2003-11-10 14:56, Dan Pop wrote:

In <3f********@new s.unimelb.edu.a u> Fergus Henderson <fj*@cs.mu.oz.a u> writes:

For size_t x and y, you have x <= SIZE_MAX && y <= SIZE_MAX,

and x + y <= SIZE_MAX iff SIZE_MAX - x >= y,

and x * y <= SIZE_MAX iff x == 0 || SIZE_MAX / x >= y.

You can hence enforce the total size limit using functions such as

the following:

size_t plus(size_t x, size_t y) {

return (SIZE_MAX - x >= y) ? x + y ; error();

}

size_t times(size_t x, size_t y) {

return (x == 0 || SIZE_MAX / x >= y) ? x * y ; error();

}

Thanks. Has anyone actually did it this way in *real* C code?

Yes, though I used type-generic macros.

Excerpt:

/*

* T is assumed to be an integer type with minimum value T_MIN and

* maximum value T_MAX. Yields +1 or -1 if the multiplication of

* a and b in T would result in an overflow or underflow,

* respectively, otherwise 0.

*

* Preconditions: (1) a and b are integer values

* (2) T is an integer type

* (3) T_MIN and T_MAX are values of integer type

* (4) T_MIN and T_MAX are valid limits of type T

* (5) T can represent a and b

*

* Does not compile if either T_MIN, T_MAX, a or b is not a numeric

* value or if T is not a numeric type.

*/

#define UT__integer_prd _ovf(T, T_MIN, T_MAX, a, b) ( \

(T)(a) > 0 \

? (T)(b) > 0 \

? (T)(T_MAX) / (T)(b) < (T)(a) ? +1 : 0 \

: (T)(T_MIN) / (T)(a) > (T)(b) ? -1 : 0 \

: (T)(b) > 0 \

? (T)(T_MIN) / (T)(b) > (T)(a) ? -1 : 0 \

: (T)(b) < 0 \

? ( (T)(T_MAX) + (T)(T_MIN) > 0 \

? ( (T)(T_MAX) / -(T)(b) < -(T)(a)) \

: (-((-(T)(T_MAX)) / (T)(b)) > (T)(a)) \

) ? +1 : 0 \

: 0 \

)

#define UT_integer_prd_ ovf(T, T_MIN, T_MAX, a, b) ( \

UT_PRECONDITION ("a is an integer value", \

UT_is_integer_v alue(a)), \

UT_PRECONDITION ("b is an integer value", \

UT_is_integer_v alue(b)), \

UT_PRECONDITION ("T is an integer type", \

UT_is_integer_t ype(T)), \

UT_PRECONDITION ("T_MIN is an integer value", \

UT_is_integer_v alue(T_MIN)), \

UT_PRECONDITION ("T_MAX is an integer value", \

UT_is_integer_v alue(T_MAX)), \

UT_PRECONDITION ("T_MIN and T_MAX are valid limits of type T", \

UT__valid_integ er_type_limits( T, T_MIN, T_MAX)), \

UT_PRECONDITION ("T can represent a", \

UT__convertible _to_integer_typ e(a, T, T_MIN, T_MAX)), \

UT_PRECONDITION ("T can represent b", \

UT__convertible _to_integer_typ e(b, T, T_MIN, T_MAX)), \

UT__integer_prd _ovf(T, T_MIN, T_MAX, a, b) \

)

[...]

#define UT_size_prd_ovf (a, b) UT_integer_prd_ ovf(size_t, 0, SIZE_MAX, a, b)

There were similar macros for all common integer types and operations,

for saturation arithmetics and so on.

-- Niklas Matthies