⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pgpmemorymgr.c

📁 PGP8.0源码 请认真阅读您的文件包然后写出其具体功能
💻 C
📖 第 1 页 / 共 2 页
字号:
/*____________________________________________________________________________
	Copyright (C) 2002 PGP Corporation
	All rights reserved.
	
	$Id: pgpMemoryMgr.c,v 1.8 2002/08/06 20:10:34 dallen Exp $
____________________________________________________________________________*/

#include "pgpPFLErrors.h"
#include "pgpMem.h"
#include "pgpPFLPriv.h"
#include "pgpRMWOLock.h"

#include "pgpMemoryMgrPriv.h"


#ifndef MEMORY_MGR_TRACK_LEAKS
/* if defined as 1, causes leaks to be tracked */
#define MEMORY_MGR_TRACK_LEAKS			PGP_DEBUG
#endif

/*____________________________________________________________________________
	This structure is prepended to every allocated block.
	
	It is dynamically padded to keep it aligned to the alignment
	requirement.  See kRealHeaderSize.
____________________________________________________________________________*/
typedef struct DataHeader
{
#define kHeaderMagic	((PGPUInt16)0xABCD)
	PGPMemoryMgrRef	mgr;
	
#if PGP_DEBUG
	/* used for tracking down leaked allocations */
	PGPUInt32		allocSeqNum;
#endif
	
	PGPUInt32		secureAlloc		: 1;
	PGPUInt32		nonPageable		: 1;
	PGPUInt32		requestSize	: 30;

#if MEMORY_MGR_TRACK_LEAKS
	struct DataHeader *	next;
	struct DataHeader *	prev;
#endif
	
	PGPUInt32		magic;
	#define kDataHeaderMagic		0x42554746  /*'BUGF'*/
} DataHeader;

#define kHeaderAlign		16
#define kOddHeaderBytes		( sizeof( DataHeader ) % kHeaderAlign )
#define kNeededHeaderBytes	( (kHeaderAlign - kOddHeaderBytes) % kHeaderAlign)
#define kRealHeaderSize		( sizeof( DataHeader ) + kNeededHeaderBytes )

#define HeaderToUserBlock( hdr )	\
	( (void *)( ((char *)(hdr)) + kRealHeaderSize) )
#define UserBlockToHeader( user )	\
	( (DataHeader *)(((char *)user) - kRealHeaderSize) )


	static PGPBoolean
sDataHeaderIsValid( const DataHeader *header )
{
	return( IsntNull( header ) &&
			IsntPGPError( PGPValidateMemoryMgr( header->mgr ) ) &&
			header->magic == kDataHeaderMagic );
}

#if PGP_DEBUG
#define AssertBlockValid( block) \
	pgpAssert( IsntNull( block ) && \
	sDataHeaderIsValid( (const DataHeader *)\
		UserBlockToHeader( block ) ) )
#else
#define AssertBlockValid( block ) /* nothing */
#endif



typedef struct PGPMemoryMgr
{
#define kPGPMemoryMgrMagic	0x4D4D6772	/* 'MMgr' */
	PGPUInt32		magic;				/* Always kPGPMemoryMgrMagic */
	PGPUserValue	customValue;		/* for custom memory mgrs */
	PGPBoolean		isDefault;
	
	PGPMemoryMgrAllocationProc		allocProc;
	PGPMemoryMgrReallocationProc	reallocProc;
	PGPMemoryMgrDeallocationProc	deallocProc;
	
	PGPMemoryMgrSecureAllocationProc	secureAllocProc;	/* may be NULL */
	PGPMemoryMgrSecureDeallocationProc	secureDeallocProc;	/* may be NULL */

#if MEMORY_MGR_TRACK_LEAKS
	PGPRMWOLock			leaksRMWOLock;
	DataHeader *		leaksList;
	DataHeader			dummyItem;
	PGPSize				numAllocations;
#endif

} PGPMemoryMgr;



	PGPError
PGPValidateMemoryMgr( PGPMemoryMgrRef mgr )
{
	PGPError	err = kPGPError_NoErr;
	
	if( IsntNull( mgr ) )
	{
		if( mgr->magic != kPGPMemoryMgrMagic )
		{
			err = kPGPError_BadParams;
		}
	}
	else
	{
		err = kPGPError_BadParams;
	}

	return( err );
}



#if MEMORY_MGR_TRACK_LEAKS	/* [ */


	static void
sCheckListIntegrity( DataHeader const * list )
{
	DataHeader *		cur		= list->next;
	const DataHeader *	prev	= list;
	
	return;	/* Disabled */
	
	/* verify that item isn't already in list */
	while ( cur != list )
	{
		pgpAssert( cur->magic == kDataHeaderMagic );
		pgpAssert( cur->prev->magic == kDataHeaderMagic );
		pgpAssert( cur->next->magic == kDataHeaderMagic );
		pgpAssert( cur->next->prev == cur && cur->prev->next == cur);
		prev = cur;
		cur	= cur->next;
	}
}

	static void
sAddToLeaksList(
	PGPMemoryMgrRef	mgr,
	DataHeader *	item )
{
#if PGP_DEBUG
	/* sequence number of allocation, used for tracking down 
	leaked allocations */
	static PGPUInt32	sAllocSeqNumber = 0;
#endif

	DataHeader *		list;
	
	PGPRMWOLockStartWriting(&mgr->leaksRMWOLock);

	list = mgr->leaksList;

	sCheckListIntegrity( list );
	
	pgpAssert( IsntNull( list->next ) && IsntNull( list->prev ) );
	
#if PGP_DEBUG
	{
		DataHeader *	cur	= list->next;
		
		/* verify that item isn't already in list */
		while ( cur != list )
		{
			pgpAssert( cur != item );
			cur	= cur->next;
		}
	}

	/* set a conditional breakpoint on the following line once
	you know the sequence number of the leaked allocation */
	item->allocSeqNum = sAllocSeqNumber;
	sAllocSeqNumber++;
#endif

	/* insert new item into circular linked list */
	item->next			= list;
	item->prev			= list->prev;
	list->prev->next	= item;
	list->prev			= item;

	mgr->numAllocations	+= 1;
	
	sCheckListIntegrity( list );
	
	pgpAssert( IsntNull( item->next ) && IsntNull( item->prev ) );

	PGPRMWOLockStopWriting(&mgr->leaksRMWOLock);

}

	static void
sRemoveFromLeaksList(
	PGPMemoryMgrRef		mgr,
	DataHeader *		item )
{
	DataHeader *	next;
	DataHeader *	prev;
	
	PGPRMWOLockStartWriting(&mgr->leaksRMWOLock);

	next	= item->next;
	prev	= item->prev;

	sCheckListIntegrity( mgr->leaksList );
	
	pgpAssert( prev->next == item && next->prev == item );
	
	next->prev	= prev;
	prev->next	= next;
	
	item->next	= NULL;
	item->prev	= NULL;
	
	mgr->numAllocations	-= 1;
	
	sCheckListIntegrity( mgr->leaksList );

	PGPRMWOLockStopWriting(&mgr->leaksRMWOLock);
}

#else
#define sAddToLeaksList( mgr, item )		/* nothing */
#define sRemoveFromLeaksList( mgr, item )	/* nothing */

#endif	/* ] */

	static void
sInitDataHeader(
	PGPMemoryMgrRef	mgr,
	PGPSize			requestSize,
	DataHeader *	header )
{
	pgpClearMemory( header, sizeof(*header) );
	header->mgr				= mgr;
	header->secureAlloc		= FALSE;
	header->nonPageable		= FALSE;
	header->requestSize	= requestSize;
	
	header->magic	= kDataHeaderMagic;
	
#if MEMORY_MGR_TRACK_LEAKS
	header->next			= NULL;
	header->prev			= NULL;
	
#endif
}




/*____________________________________________________________________________
	Reallocate a secure block.
	
	To preserve the semantics of the block not changing if it shrinks,
	we take no action if the block is shrinking.  If it's growing, we
	always discard it and create a new one.
____________________________________________________________________________*/
	static PGPError
sSecureMemoryReallocProc(
	PGPMemoryMgrRef		mgr,
	void **				allocation,
	PGPSize 			newAllocationSize,
	PGPMemoryMgrFlags	flags,
	PGPSize				existingSize )
{
	PGPError		err		= kPGPError_NoErr;
	
	pgpAssert( IsntNull( *allocation ) );
	
#if 0
	if ( newAllocationSize <= existingSize )
	{
		PGPUInt32	excessByteCount;
		char *		dataToClear	= NULL;
		
		/* leave existing size intact, but clear excess bytes now
		to avoid leaving sensitive data in memory unnecessarily */
		excessByteCount	= existingSize - newAllocationSize;
		dataToClear	= ((char *)*allocation) + newAllocationSize;
		pgpClearMemory( dataToClear, excessByteCount );
		
		err	= kPGPError_NoErr;
	}
	else
#endif
	{	/* block is increasing in size */
		PGPBoolean	isNonPageable;
		void *		newBlock	= NULL;
		
		newBlock	= (mgr->secureAllocProc)( mgr, mgr->customValue,
			newAllocationSize, flags, &isNonPageable);
		if ( IsntNull( newBlock ) )
		{
			DataHeader *	oldHeader	= (DataHeader *)*allocation;

			pgpCopyMemory( *allocation, newBlock,
				pgpMin( existingSize, newAllocationSize ) );
			
			(mgr->secureDeallocProc)( mgr, mgr->customValue,
				*allocation, existingSize,
				(PGPBoolean)oldHeader->nonPageable );
			*allocation	= newBlock;
		}
		else
		{
			err	= kPGPError_OutOfMemory;
		}
	}
	
	return( err );
}




/*____________________________________________________________________________
	Allocate a new Memory Mgr using custom memory allocators.
____________________________________________________________________________*/
	PGPError
PGPNewMemoryMgrCustom(
	PGPNewMemoryMgrStruct const *	custom,
	PGPMemoryMgrRef *				newMgr )
{
	PGPError			err = kPGPError_NoErr;
	PGPMemoryMgrRef		mgr	= NULL;
	PGPUInt32			idx;
	
	PGPValidatePtr( newMgr );
	*newMgr	= NULL;
	PGPValidatePtr( custom );
	PGPValidatePtr( custom->allocProc );
	PGPValidatePtr( custom->reallocProc );
	PGPValidatePtr( custom->deallocProc );
	PGPValidatePtr( custom->secureAllocProc );
	PGPValidatePtr( custom->secureDeallocProc );
	PGPValidateParam( custom->sizeofStruct >= sizeof( *custom ) );
	PGPValidateParam( custom->reserved == NULL );
	
	#define kNumPads	sizeof( custom->pad ) / sizeof( custom->pad[ 0 ] )
	for( idx = 0; idx < kNumPads; ++idx )
	{
		PGPValidateParam( custom->pad[ idx ] == NULL );
	}
	
	/* NOTE: do not depend on kPGPMemoryMgrFlags_Clear here;
	 allocator is not required to support it */
	mgr = (PGPMemoryMgr *) (*(custom->allocProc))( NULL, custom->customValue,
				sizeof( *mgr ), 0 );
	if( IsntNull( mgr ) )
	{
		pgpClearMemory( mgr, sizeof( *mgr ) );
		mgr->magic				= kPGPMemoryMgrMagic;
		mgr->allocProc			= custom->allocProc;
		mgr->reallocProc		= custom->reallocProc;
		mgr->deallocProc		= custom->deallocProc;
		mgr->secureAllocProc	= custom->secureAllocProc;
		mgr->secureDeallocProc	= custom->secureDeallocProc;

		mgr->customValue		= custom->customValue;
		mgr->isDefault			= FALSE;
		
#if MEMORY_MGR_TRACK_LEAKS
		/* Create read many/write once mutex. */
		InitializePGPRMWOLock(&mgr->leaksRMWOLock);

		/* set up doubly-linked leaks list */
		mgr->leaksList			= &mgr->dummyItem;
		mgr->dummyItem.next		= &mgr->dummyItem;
		mgr->dummyItem.prev		= &mgr->dummyItem;
		mgr->dummyItem.magic	= kDataHeaderMagic;
		mgr->numAllocations		= 0;
#endif
	}
	else
	{
		err = kPGPError_OutOfMemory;
	}
	
	*newMgr	= mgr;
	
	return( err );
}


/*____________________________________________________________________________
____________________________________________________________________________*/

	PGPError
PGPNewMemoryMgr(
	PGPFlags			reserved,
	PGPMemoryMgrRef *	newMgr )
{
	PGPError	err	= kPGPError_NoErr;
	
	PGPValidatePtr( newMgr );
	*newMgr	= NULL;
	PGPValidateParam( reserved == 0 );
	
	err	= pgpCreateStandardMemoryMgr( newMgr );
	if ( IsntPGPError( err ) )
	{
		(*newMgr)->isDefault	= TRUE;
	}
	
	return( err );
}



/*____________________________________________________________________________
	Delete an existing PFLContext and all resources associated with it.
____________________________________________________________________________*/
	PGPError
PGPFreeMemoryMgr(PGPMemoryMgrRef	mgr)
{
	PGPError	err = kPGPError_NoErr;
	
	err = PGPValidateMemoryMgr( mgr );
	if( IsntPGPError( err ) )
	{
		PGPUserValue	customValue	= mgr->customValue;
		PGPBoolean		isDefault	= mgr->isDefault;
		
#if MEMORY_MGR_TRACK_LEAKS
		DeletePGPRMWOLock(&mgr->leaksRMWOLock);

		pgpAssertMsg( mgr->numAllocations == 0,
		"PGPFreeData(): mgr being freed with outstanding allocations" );
#endif
		
		(*mgr->deallocProc)( NULL, customValue, mgr, sizeof( *mgr ));
		
		if ( isDefault )
		{
			pgpDisposeStandardMemoryMgrUserValue( customValue );
		}
		
	}
	
	return( err );
}


	PGPError

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -