Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[ace-bugs] Bug in Message_Block::clone that takes too much memory

63 views
Skip to first unread message

Pierre Bisaillon

unread,
Jun 5, 2012, 3:56:37 PM6/5/12
to ace-...@list.isis.vanderbilt.edu

ACE VERSION: 6.1.2

HOST MACHINE and OPERATING SYSTEM: Windows 7 SP1

COMPILER NAME AND VERSION: VS2008 SP1

AREA/CLASS/EXAMPLE AFFECTED: Message_Block::clone

DOES THE PROBLEM AFFECT:

EXECUTION?

The Message_Block::clone method allocates too much memory

SYNOPSIS: When using a specially crafted Message_Block chain, similar to one that might be build by TAO, the close method will allocate too much memory

DESCRIPTION:

The following method builds a message block chain similar to what TAO might build when a method expects to receive an array of strings. It is composed of one data block, of size 1,000,000 bytes and a multitude of Message_Blocks that point into this Data_Block.

When the clone method is called on this chain, each Message_Block will copy the full 1,000,000 bytes buffer instead of only copying the appropriate size from the large data block.

REPEAT BY:

Trying to execute this test in the Message_Block_test.cpp test:

int DoTest2()

{

// prepare data block so it simulates an array of strings...

size_t datalen(1000000);

ACE_Data_Block dataBlock(datalen, ACE_Message_Block::MB_DATA, 0,0, 0, 0, 0);

ACE_Message_Block mainBlock(&dataBlock, ACE_Message_Block::DONT_DELETE, 0);

for (ACE_Message_Block *ptr = &mainBlock; datalen > 0;)

{

#undef min

ACE_CDR::ULong size = 11;

size_t toCopy(std::min(datalen, sizeof(size) + size));

if (toCopy < sizeof(size))

break; // no more space

size = toCopy - sizeof(size);

ACE_OS::memcpy(ptr->wr_ptr(), &size, sizeof(size));

ptr->wr_ptr(sizeof(size));

ACE_OS::memcpy(ptr->wr_ptr(), "1234567890", size);

ptr->wr_ptr(size);

if (size == 11)

{ // create next block only if not last block

ACE_Message_Block *cont = ACE_Message_Block::duplicate(ptr);

cont->rd_ptr(cont->wr_ptr());

ptr->cont(cont);

ptr = cont;

}

datalen -= toCopy;

}

// now, clone the mainblock:

// this should take a lot of memory, probably the program will crash, or on Windows, the system will hang

ACE_Message_Block *clonedBlock = mainBlock.clone();

// release all allocated memory

clonedBlock->release();

mainBlock.cont()->release();

return 0;

}

SAMPLE FIX/WORKAROUND:

The following seems to correct the problem:

--- C:/cvsdata/third-party4.3/ACE_wrappers/ace/Message_Block.cpp mer. sept. 21 10:51:23 2011

+++ C:/cvsdata/third-party4.3/ACE_wrappers/ace/Message_Block - copy.cpp mar. juin 5 12:14:40 2012

@@ -1182,11 +1182,27 @@

{

// Get a pointer to a "cloned"<ACE_Data_Block> (will copy the

// values rather than increment the reference count).

- ACE_Data_Block *db = old_message_block->data_block ()->clone (mask);

+ ACE_Data_Block *oldBlock = old_message_block->data_block();

+ ACE_Data_Block *db(0);

+ ACE_NEW_MALLOC_RETURN (db,

+ static_cast<ACE_Data_Block*> (

+ oldBlock->data_block_allocator()->malloc (sizeof (ACE_Data_Block))),

+ ACE_Data_Block (old_message_block->length(), // size

+ oldBlock->msg_type(), // type

+ 0, // data

+ oldBlock->allocator_strategy(), // allocator

+ oldBlock->locking_strategy(), // locking strategy

+ oldBlock->flags(), // flags

+ oldBlock->data_block_allocator()),

+ 0);

+

if (db == 0)

return 0;

+ db->clr_flags(ACE_Message_Block::DONT_DELETE);

+ ACE_OS::memcpy(db->base(), old_message_block->rd_ptr (), old_message_block->length());

+

if(old_message_block->message_block_allocator_ == 0)

{

ACE_NEW_RETURN (new_message_block,

@@ -1241,8 +1257,7 @@

// Set the read and write pointers in the new <Message_Block> to the

// same relative offset as in the existing <Message_Block>.

- new_message_block->rd_ptr (old_message_block->rd_ptr_);

- new_message_block->wr_ptr (old_message_block->wr_ptr_);

+ new_message_block->wr_ptr (old_message_block->length());

// save the root message block to return

if (new_root_message_block == 0)

new_root_message_block = new_message_block;

 

Johnny Willemsen

unread,
Jun 6, 2012, 1:49:49 AM6/6/12
to Pierre Bisaillon, ace-...@list.isis.vanderbilt.edu
Hi,

Thanks for using the PRF form. Could you take the existing
ACE_wrappers/tests/Message_Block_Test.cpp and update it to just
reproduce this issue? Create a main that just tests this bug, but
instead of letting it hang, use the mb length/size methods to log what
kind of length/size you expect and what it gets. that way we have a one
button test which we can use in the test suite. When you have that, can
you add the new test with your proposed fix to bugzilla at
http://bugzilla.dre.vanderbilt.edu/

Best regards,

Johnny Willemsen
Remedy IT
> _______________________________________________
> ace-bugs mailing list
> ace-...@list.isis.vanderbilt.edu
> http://list.isis.vanderbilt.edu/mailman/listinfo/ace-bugs

0 new messages