2006-10-07 04:25 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/include/hbclass.ch
+ added validation for class data names. As additional preprocessor
rule to not use <!marker!>
* harbour/include/hboo.ch
* harbour/source/rtl/tclass.prg
* harbour/source/vm/classes.c
+ added delegate messages
* harbour/include/hbstack.h
* harbour/source/vm/arrays.c
* harbour/source/vm/estack.c
* harbour/source/vm/hvm.c
* harbour/source/vm/proc.c
+ added startup symbol to hb_stack. It gives very good stop
condition for all procedures which trace stack calls and
resolves the problem with hb_stack.pBase which was never
pointing to valid function/procedure symbol when no symbol
was put on HVM stack. Now after hb_stackInit() the first
item is allocated for "hb_stackInit()" symbol so hb_stack.pBase
is always a pointer to valid function/procedure symbol.
* changed the guard condition for buggy code in hb_stackPop()
and similar code from:
hb_stack.pPos < hb_stack.pItems
to:
hb_stack.pPos <= hb_stack.pBase
The old condition was generating usable error message only in the
startup function. In deeply called functions it was only waste of
CPU time on one of the most often call functions. Before it was
activated internal stack structures were corrupted.
If we were leaving for many years without really working stack
underflow protection then maybe we should think about disabling
it at when HB_STACK_MACROS are used and keep it only in real
stack functions for HVM developers. Single protection in
hb_stackOldFrame() I've just added is enough for basic C code
validation.
I created the second version of stack macros without it in
hbstack.h but I would like to hear other developers opinion.
This commit is contained in:
@@ -76,6 +76,7 @@ typedef struct
|
||||
PHB_ITEM * pEvalBase; /* stack frame position for the evaluated codeblock */
|
||||
LONG lStatics; /* statics base for the current function call */
|
||||
LONG lWithObject; /* stack offset to base current WITH OBJECT item */
|
||||
HB_STACK_STATE state; /* first (default) stack state frame */
|
||||
char szDate[ 9 ]; /* last returned date from _pards() yyyymmdd format */
|
||||
} HB_STACK;
|
||||
|
||||
@@ -121,8 +122,8 @@ extern void hb_stackIncrease( void ); /* increase the stack size */
|
||||
|
||||
#ifdef _HB_API_INTERNAL_
|
||||
extern void hb_stackDecrease( ULONG ulItems );
|
||||
extern HB_ITEM_PTR hb_stackNewFrame( HB_STACK_STATE * pStack, USHORT uiParams );
|
||||
extern void hb_stackOldFrame( HB_STACK_STATE * pStack );
|
||||
extern HB_ITEM_PTR hb_stackNewFrame( PHB_STACK_STATE pStack, USHORT uiParams );
|
||||
extern void hb_stackOldFrame( PHB_STACK_STATE pStack );
|
||||
extern void hb_stackClearMevarsBase( void );
|
||||
#endif
|
||||
|
||||
@@ -149,45 +150,67 @@ extern void hb_stackClearMevarsBase( void );
|
||||
hb_stackIncrease() : (void) 0 ), \
|
||||
* ( hb_stack.pPos - 1 ) )
|
||||
|
||||
#ifdef HB_STACK_SAFEMACROS
|
||||
|
||||
#define hb_stackDecrease( n ) do { \
|
||||
if( ( hb_stack.pPos -= (n) ) < hb_stack.pItems ) \
|
||||
if( ( hb_stack.pPos -= (n) ) <= hb_stack.pBase ) \
|
||||
hb_errInternal( HB_EI_STACKUFLOW, NULL, NULL, NULL ); \
|
||||
} while ( 0 )
|
||||
|
||||
#define hb_stackDec( ) do { \
|
||||
if( --hb_stack.pPos < hb_stack.pItems ) \
|
||||
if( --hb_stack.pPos <= hb_stack.pBase ) \
|
||||
hb_errInternal( HB_EI_STACKUFLOW, NULL, NULL, NULL ); \
|
||||
} while ( 0 )
|
||||
|
||||
#define hb_stackPop( ) do { \
|
||||
if( --hb_stack.pPos < hb_stack.pItems ) \
|
||||
if( --hb_stack.pPos <= hb_stack.pBase ) \
|
||||
hb_errInternal( HB_EI_STACKUFLOW, NULL, NULL, NULL ); \
|
||||
if( HB_IS_COMPLEX( * hb_stack.pPos ) ) \
|
||||
hb_itemClear( * hb_stack.pPos ); \
|
||||
} while ( 0 )
|
||||
|
||||
#define hb_stackPush( ) do { \
|
||||
if( ++hb_stack.pPos == hb_stack.pEnd ) \
|
||||
hb_stackIncrease(); \
|
||||
} while ( 0 )
|
||||
|
||||
#define hb_stackPopReturn( ) do { \
|
||||
if( HB_IS_COMPLEX( &hb_stack.Return ) ) \
|
||||
hb_itemClear( &hb_stack.Return ); \
|
||||
if( --hb_stack.pPos < hb_stack.pItems ) \
|
||||
if( --hb_stack.pPos <= hb_stack.pBase ) \
|
||||
hb_errInternal( HB_EI_STACKUFLOW, NULL, NULL, NULL ); \
|
||||
hb_itemRawMove( &hb_stack.Return, * hb_stack.pPos ); \
|
||||
} while ( 0 )
|
||||
|
||||
#else
|
||||
|
||||
#define hb_stackDecrease( n ) do { hb_stack.pPos -= (n); } while ( 0 )
|
||||
#define hb_stackDec( ) do { --hb_stack.pPos; } while ( 0 )
|
||||
#define hb_stackPop( ) do { --hb_stack.pPos; \
|
||||
if( HB_IS_COMPLEX( * hb_stack.pPos ) ) \
|
||||
hb_itemClear( * hb_stack.pPos ); \
|
||||
} while ( 0 )
|
||||
#define hb_stackPopReturn( ) do { \
|
||||
if( HB_IS_COMPLEX( &hb_stack.Return ) ) \
|
||||
hb_itemClear( &hb_stack.Return ); \
|
||||
--hb_stack.pPos; \
|
||||
hb_itemRawMove( &hb_stack.Return, * hb_stack.pPos ); \
|
||||
} while ( 0 )
|
||||
|
||||
#endif
|
||||
|
||||
#define hb_stackPush( ) do { \
|
||||
if( ++hb_stack.pPos == hb_stack.pEnd ) \
|
||||
hb_stackIncrease(); \
|
||||
} while ( 0 )
|
||||
|
||||
#define hb_stackPushReturn( ) do { \
|
||||
hb_itemRawMove( * hb_stack.pPos, &hb_stack.Return ); \
|
||||
if( ++hb_stack.pPos == hb_stack.pEnd ) \
|
||||
hb_stackIncrease(); \
|
||||
} while ( 0 )
|
||||
#define hb_stackLocalVariable( p ) ((((*hb_stack.pBase)->item.asSymbol.paramcnt > (*hb_stack.pBase)->item.asSymbol.paramdeclcnt) && \
|
||||
(*(p)) > (*hb_stack.pBase)->item.asSymbol.paramdeclcnt ) ? \
|
||||
(* ( hb_stack.pBase + ( int ) ((*(p))+=((*hb_stack.pBase)->item.asSymbol.paramcnt - (*hb_stack.pBase)->item.asSymbol.paramdeclcnt)) + 1 ) ) : \
|
||||
(* ( hb_stack.pBase + ( int ) (*(p)) + 1 ) ) )
|
||||
#define hb_stackLocalVariable( p ) ( ( ( ( *hb_stack.pBase )->item.asSymbol.paramcnt > \
|
||||
( * hb_stack.pBase )->item.asSymbol.paramdeclcnt ) && \
|
||||
( * (p) ) > ( * hb_stack.pBase )->item.asSymbol.paramdeclcnt ) ? \
|
||||
( * ( hb_stack.pBase + ( int ) ( * (p) += \
|
||||
( * hb_stack.pBase )->item.asSymbol.paramcnt - \
|
||||
( * hb_stack.pBase )->item.asSymbol.paramdeclcnt ) + 1 ) ) : \
|
||||
( * ( hb_stack.pBase + ( int ) ( * (p) ) + 1 ) ) )
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user