J
jacob navia
Abstract:
Overflow checking is not done in C. This article proposes a solution
to close this hole in the language that has almost no impact in the run
time behavior.
1: The situation now
--------------------
Any of the four operations on signed integers can overflow. The result
of the operation is meaningless, what can have a catastrophic impact
on the operations that follow. There are important security issues
associated with overflows.
The only way to catch overflows now is to use cumbersome C expressions
that force modifications of source code, and are very slow since done
in C.
2: The proposed solution
------------------------
In the experimental compiler lcc-win, I have implemented since 2003 an
overflow checking mechanism.
From that work I have derived this proposal.
2.A: A new pragma
------------------
#pragma STDC OVERFLOW_CHECK on_off_flag
When in the ON state, any overflow of an addition, subtraction,
multiplication or division provokes a call to the overflow handler.
Operations like +=, -=, *=, and /= are counted also.
Only the types signed int and signed long long are concerned.
The initial state of the overflow flag is implementation defined.
2.B: Setting the handler for overflows
---------------------------------------
overflow_handler_t set_overflow_handler(overflow_handler_t newvalue);
The function set_overflow_handler sets the function to be called in
case of overflow to the specified value. If "newvalue" is NULL,
the function sets the handler to the default value (the value
it had at program startup).
2.C: The handler function
-------------------------
typedef void (*overflow_handler_t)(unsigned line_number,
char *filename,
char *function_name,...);
This function will be called when an overflow is detected. The
arguments have the same values as __LINE__ __FILE__ and __FUNC__
If this function returns, execution continues with an implementation
defined value as the result of the operation that overflowed.
-------------------------------------------------------------------
Implementation.
I have implemented this solution, and the overhead is almost zero.
The most important point for implementors is to realize that the
normal flow (i.e. when there is no overflow) should not be disturbed.
No overhead implementation:
--------------------------
1. Perform operation (add, subtract, etc)
2. Jump on overflow to an error label
3: Go on with the rest of the program
The overhead of this is below accuracy in a PC system.
It can't be measured.
Implementation with small overhead (3-5%)
1. Perform operation
2. If no overflow jump to continuation
3. save registers
4. Push arguments
5. Call handler
6. Pop arguments
7. Restore registers
continuation:
The problem with the second implementation is that the flow of control
is disturbed. The branch to the continuation code will be mispredicted
since it is a forward branch. This provokes pipeline turbulence.
The first solution provokes no pipeline turbulence since the forward
jump will be predicted as not taken. This will be a good prediction
in the overwhelming majority of situations (no overflow). The only
overhead is just an additional instruction, i.e. almost nothing.
----------------------------------------------------------------------
Overflow checking is not done in C. This article proposes a solution
to close this hole in the language that has almost no impact in the run
time behavior.
1: The situation now
--------------------
Any of the four operations on signed integers can overflow. The result
of the operation is meaningless, what can have a catastrophic impact
on the operations that follow. There are important security issues
associated with overflows.
The only way to catch overflows now is to use cumbersome C expressions
that force modifications of source code, and are very slow since done
in C.
2: The proposed solution
------------------------
In the experimental compiler lcc-win, I have implemented since 2003 an
overflow checking mechanism.
From that work I have derived this proposal.
2.A: A new pragma
------------------
#pragma STDC OVERFLOW_CHECK on_off_flag
When in the ON state, any overflow of an addition, subtraction,
multiplication or division provokes a call to the overflow handler.
Operations like +=, -=, *=, and /= are counted also.
Only the types signed int and signed long long are concerned.
The initial state of the overflow flag is implementation defined.
2.B: Setting the handler for overflows
---------------------------------------
overflow_handler_t set_overflow_handler(overflow_handler_t newvalue);
The function set_overflow_handler sets the function to be called in
case of overflow to the specified value. If "newvalue" is NULL,
the function sets the handler to the default value (the value
it had at program startup).
2.C: The handler function
-------------------------
typedef void (*overflow_handler_t)(unsigned line_number,
char *filename,
char *function_name,...);
This function will be called when an overflow is detected. The
arguments have the same values as __LINE__ __FILE__ and __FUNC__
If this function returns, execution continues with an implementation
defined value as the result of the operation that overflowed.
-------------------------------------------------------------------
Implementation.
I have implemented this solution, and the overhead is almost zero.
The most important point for implementors is to realize that the
normal flow (i.e. when there is no overflow) should not be disturbed.
No overhead implementation:
--------------------------
1. Perform operation (add, subtract, etc)
2. Jump on overflow to an error label
3: Go on with the rest of the program
The overhead of this is below accuracy in a PC system.
It can't be measured.
Implementation with small overhead (3-5%)
1. Perform operation
2. If no overflow jump to continuation
3. save registers
4. Push arguments
5. Call handler
6. Pop arguments
7. Restore registers
continuation:
The problem with the second implementation is that the flow of control
is disturbed. The branch to the continuation code will be mispredicted
since it is a forward branch. This provokes pipeline turbulence.
The first solution provokes no pipeline turbulence since the forward
jump will be predicted as not taken. This will be a good prediction
in the overwhelming majority of situations (no overflow). The only
overhead is just an additional instruction, i.e. almost nothing.
----------------------------------------------------------------------