bug #90394: r=dbaron, sr=asa(?). A simple fix to a big leak when |nsXPIDLC?String|s are never accessed after assignment, deallocation failed. By storing the initial pointer in the _storage_ start slot, this is avoided.

This commit is contained in:
scc%mozilla.org 2001-07-12 06:48:23 +00:00
Родитель d39b3e59c8
Коммит be36f3d342
4 изменённых файлов: 42 добавлений и 34 удалений

Просмотреть файл

@ -43,11 +43,16 @@
* must be called before any other object can share the buffer,
* and as the default implementation for |GetBufferHandle|, which is
* the operation on which all other flat string operations are based.
* A valid handle always contains a non-|NULL| data start and end.
* After use as an `out' string pointer parameter, an |nsXPIDLC?String|'s
* handle will have a non-|NULL| data start, but its data end will be
* |NULL|. This is the signal that the length needs to be recalculated.
* |GetSharedBufferHandle| detects this situation and repairs it.
* A valid handle will either have all |NULL| or all non-|NULL|
* pointers. After use as an `out' string pointer parameter, an
* |nsXPIDLC?String|'s handle will have a non-|NULL| storage start, but
* all other members will be |NULL|. This is the signal that the
* length needs to be recalculated. |GetSharedBufferHandle| detects
* this situation and repairs it.
*
* The one situation this _doesn't_ catch, is if no one ever tries to use
* the string before it's destruction. In this case, because the start of
* storage is known, storage can still be freed in the usual way.
*
* An |nsXPIDLC?String| is now a sharable object, just like |nsSharableC?String|.
* This simple implementation always allocates an intermediary handle

Просмотреть файл

@ -45,7 +45,7 @@ class nsImportedStringHandle
public:
nsImportedStringHandle() : nsFlexBufferHandle<CharT>(0, 0, 0, 0) { }
CharT** AddressOfDataStart() { return &(this->mDataStart); }
CharT** AddressOfStorageStart() { return &(this->mStorageStart); }
void RecalculateBoundaries() const;
};
@ -57,18 +57,17 @@ nsImportedStringHandle<CharT>::RecalculateBoundaries() const
size_t data_length = 0;
size_t storage_length = 0;
CharT* data_start = NS_CONST_CAST(CharT*, this->DataStart());
if ( data_start )
CharT* storage_start = NS_CONST_CAST(CharT*, this->StorageStart());
if ( storage_start )
{
data_length = nsCharTraits<CharT>::length(data_start);
data_length = nsCharTraits<CharT>::length(storage_start);
storage_length = data_length + 1;
}
nsImportedStringHandle<CharT>* mutable_this = NS_CONST_CAST(nsImportedStringHandle<CharT>*, this);
mutable_this->DataEnd(data_start+data_length);
mutable_this->StorageStart(data_start);
mutable_this->StorageEnd(data_start+storage_length);
mutable_this->DataStart(storage_start);
mutable_this->DataEnd(storage_start+data_length);
mutable_this->StorageEnd(storage_start+storage_length);
}
@ -103,7 +102,7 @@ nsXPIDLString::GetSharedBufferHandle() const
{
const nsImportedStringHandle<PRUnichar>* answer = NS_STATIC_CAST(const nsImportedStringHandle<PRUnichar>*, mBuffer.get());
if ( answer && !answer->DataEnd() )
if ( answer && !answer->DataEnd() && answer->StorageStart() )
answer->RecalculateBoundaries();
#if DEBUG_STRING_STATS
@ -123,7 +122,7 @@ nsXPIDLString::PrepareForUseAsOutParam()
#if DEBUG_STRING_STATS
++sAssignCount;
#endif
return handle->AddressOfDataStart();
return handle->AddressOfStorageStart();
}
@ -158,7 +157,7 @@ nsXPIDLCString::GetSharedBufferHandle() const
{
const nsImportedStringHandle<char>* answer = NS_STATIC_CAST(const nsImportedStringHandle<char>*, mBuffer.get());
if ( answer && !answer->DataEnd() )
if ( answer && !answer->DataEnd() && answer->StorageStart() )
answer->RecalculateBoundaries();
#if DEBUG_STRING_STATS
@ -178,5 +177,5 @@ nsXPIDLCString::PrepareForUseAsOutParam()
#if DEBUG_STRING_STATS
++sAssignCount;
#endif
return handle->AddressOfDataStart();
return handle->AddressOfStorageStart();
}

Просмотреть файл

@ -43,11 +43,16 @@
* must be called before any other object can share the buffer,
* and as the default implementation for |GetBufferHandle|, which is
* the operation on which all other flat string operations are based.
* A valid handle always contains a non-|NULL| data start and end.
* After use as an `out' string pointer parameter, an |nsXPIDLC?String|'s
* handle will have a non-|NULL| data start, but its data end will be
* |NULL|. This is the signal that the length needs to be recalculated.
* |GetSharedBufferHandle| detects this situation and repairs it.
* A valid handle will either have all |NULL| or all non-|NULL|
* pointers. After use as an `out' string pointer parameter, an
* |nsXPIDLC?String|'s handle will have a non-|NULL| storage start, but
* all other members will be |NULL|. This is the signal that the
* length needs to be recalculated. |GetSharedBufferHandle| detects
* this situation and repairs it.
*
* The one situation this _doesn't_ catch, is if no one ever tries to use
* the string before it's destruction. In this case, because the start of
* storage is known, storage can still be freed in the usual way.
*
* An |nsXPIDLC?String| is now a sharable object, just like |nsSharableC?String|.
* This simple implementation always allocates an intermediary handle

Просмотреть файл

@ -45,7 +45,7 @@ class nsImportedStringHandle
public:
nsImportedStringHandle() : nsFlexBufferHandle<CharT>(0, 0, 0, 0) { }
CharT** AddressOfDataStart() { return &(this->mDataStart); }
CharT** AddressOfStorageStart() { return &(this->mStorageStart); }
void RecalculateBoundaries() const;
};
@ -57,18 +57,17 @@ nsImportedStringHandle<CharT>::RecalculateBoundaries() const
size_t data_length = 0;
size_t storage_length = 0;
CharT* data_start = NS_CONST_CAST(CharT*, this->DataStart());
if ( data_start )
CharT* storage_start = NS_CONST_CAST(CharT*, this->StorageStart());
if ( storage_start )
{
data_length = nsCharTraits<CharT>::length(data_start);
data_length = nsCharTraits<CharT>::length(storage_start);
storage_length = data_length + 1;
}
nsImportedStringHandle<CharT>* mutable_this = NS_CONST_CAST(nsImportedStringHandle<CharT>*, this);
mutable_this->DataEnd(data_start+data_length);
mutable_this->StorageStart(data_start);
mutable_this->StorageEnd(data_start+storage_length);
mutable_this->DataStart(storage_start);
mutable_this->DataEnd(storage_start+data_length);
mutable_this->StorageEnd(storage_start+storage_length);
}
@ -103,7 +102,7 @@ nsXPIDLString::GetSharedBufferHandle() const
{
const nsImportedStringHandle<PRUnichar>* answer = NS_STATIC_CAST(const nsImportedStringHandle<PRUnichar>*, mBuffer.get());
if ( answer && !answer->DataEnd() )
if ( answer && !answer->DataEnd() && answer->StorageStart() )
answer->RecalculateBoundaries();
#if DEBUG_STRING_STATS
@ -123,7 +122,7 @@ nsXPIDLString::PrepareForUseAsOutParam()
#if DEBUG_STRING_STATS
++sAssignCount;
#endif
return handle->AddressOfDataStart();
return handle->AddressOfStorageStart();
}
@ -158,7 +157,7 @@ nsXPIDLCString::GetSharedBufferHandle() const
{
const nsImportedStringHandle<char>* answer = NS_STATIC_CAST(const nsImportedStringHandle<char>*, mBuffer.get());
if ( answer && !answer->DataEnd() )
if ( answer && !answer->DataEnd() && answer->StorageStart() )
answer->RecalculateBoundaries();
#if DEBUG_STRING_STATS
@ -178,5 +177,5 @@ nsXPIDLCString::PrepareForUseAsOutParam()
#if DEBUG_STRING_STATS
++sAssignCount;
#endif
return handle->AddressOfDataStart();
return handle->AddressOfStorageStart();
}