The result of some more proof-reading caused by Stephan's comments:

* _Realloc(), and _Detach[With]() may fail, but that wasn't accounted for
  everywhere.
* The Append(), Prepend(), and Insert() char versions all caused their
  backends to access invalid data (must use strncpy() instead of memcpy()
  here). 
* All Append(), Prepend(), and Insert() BString variants used an invalid
  check, and would therefore just do nothing in certain situations like this
  one:
    BString a = "-";
    BString b = a;
    a.Append(b);


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24347 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2008-03-10 16:41:43 +00:00
parent 8a1c136e47
commit 7c58a46830
+29 -19
View File
@@ -155,7 +155,9 @@ BStringRef::operator&() const
char* char*
BStringRef::operator&() BStringRef::operator&()
{ {
fString._Detach(); if (fString._Detach() != B_OK)
return NULL;
fString._ReferenceCount() = -1; fString._ReferenceCount() = -1;
// mark as unsharable // mark as unsharable
return &fString.fPrivateData[fPosition]; return &fString.fPrivateData[fPosition];
@@ -385,7 +387,8 @@ BString::operator+=(char c)
BString& BString&
BString::Append(const BString& string, int32 length) BString::Append(const BString& string, int32 length)
{ {
_DoAppend(string.fPrivateData, min_clamp0(length, string.Length())); if (&string != this)
_DoAppend(string.fPrivateData, min_clamp0(length, string.Length()));
return *this; return *this;
} }
@@ -424,8 +427,8 @@ BString::Prepend(const char* string)
BString& BString&
BString::Prepend(const BString& string) BString::Prepend(const BString& string)
{ {
if (fPrivateData != string.fPrivateData) if (&string != this)
_DoPrepend(string.fPrivateData, string.Length()); _DoPrepend(string.String(), string.Length());
return *this; return *this;
} }
@@ -442,7 +445,7 @@ BString::Prepend(const char* string, int32 length)
BString& BString&
BString::Prepend(const BString& string, int32 length) BString::Prepend(const BString& string, int32 length)
{ {
if (fPrivateData != string.fPrivateData) if (&string != this)
_DoPrepend(string.fPrivateData, min_clamp0(length, string.Length())); _DoPrepend(string.fPrivateData, min_clamp0(length, string.Length()));
return *this; return *this;
} }
@@ -511,7 +514,7 @@ BString::Insert(const char* string, int32 fromOffset, int32 length,
BString& BString&
BString::Insert(const BString& string, int32 position) BString::Insert(const BString& string, int32 position)
{ {
if ((fPrivateData != string.fPrivateData) && string.Length() > 0) if (&string != this && string.Length() > 0)
Insert(string.fPrivateData, position); Insert(string.fPrivateData, position);
return *this; return *this;
} }
@@ -520,7 +523,7 @@ BString::Insert(const BString& string, int32 position)
BString& BString&
BString::Insert(const BString& string, int32 length, int32 position) BString::Insert(const BString& string, int32 length, int32 position)
{ {
if ((fPrivateData != string.fPrivateData) && string.Length() > 0) if (&string != this && string.Length() > 0)
Insert(string.String(), length, position); Insert(string.String(), length, position);
return *this; return *this;
} }
@@ -530,7 +533,7 @@ BString&
BString::Insert(const BString& string, int32 fromOffset, int32 length, BString::Insert(const BString& string, int32 fromOffset, int32 length,
int32 position) int32 position)
{ {
if ((fPrivateData != string.fPrivateData) && string.Length() > 0) if (&string != this && string.Length() > 0)
Insert(string.String() + fromOffset, length, position); Insert(string.String() + fromOffset, length, position);
return *this; return *this;
} }
@@ -1381,8 +1384,13 @@ BString::operator[](int32 index)
char& char&
BString::operator[](int32 index) BString::operator[](int32 index)
{ {
_Detach(); if (_Detach() != B_OK) {
static char invalid;
return invalid;
}
_ReferenceCount() = -1; _ReferenceCount() = -1;
// mark string as unshareable
return fPrivateData[index]; return fPrivateData[index];
} }
@@ -1399,9 +1407,10 @@ BString::LockBuffer(int32 maxLength)
if (maxLength > length) if (maxLength > length)
length += maxLength - length; length += maxLength - length;
_DetachWith(fPrivateData, length); if (_DetachWith(fPrivateData, length) == B_OK) {
_ReferenceCount() = -1; _ReferenceCount() = -1;
// mark unshareable // mark unshareable
}
return fPrivateData; return fPrivateData;
} }
@@ -1416,10 +1425,11 @@ BString::UnlockBuffer(int32 length)
length = (fPrivateData == NULL) ? 0 : strlen(fPrivateData); length = (fPrivateData == NULL) ? 0 : strlen(fPrivateData);
} }
_Realloc(length); if (_Realloc(length) != NULL) {
fPrivateData[length] = '\0'; fPrivateData[length] = '\0';
_ReferenceCount() = 1; _ReferenceCount() = 1;
// mark shareable again // mark shareable again
}
return *this; return *this;
} }
@@ -1819,7 +1829,7 @@ BString::_DoAppend(const char* string, int32 length)
int32 oldLength = Length(); int32 oldLength = Length();
if (_DetachWith(fPrivateData, oldLength + length) == B_OK) { if (_DetachWith(fPrivateData, oldLength + length) == B_OK) {
if (string && length) if (string && length)
memcpy(fPrivateData + oldLength, string, length); strncpy(fPrivateData + oldLength, string, length);
return true; return true;
} }
return false; return false;
@@ -1833,7 +1843,7 @@ BString::_DoPrepend(const char* string, int32 length)
if (_DetachWith(fPrivateData, oldLength + length) == B_OK) { if (_DetachWith(fPrivateData, oldLength + length) == B_OK) {
memmove(fPrivateData + length, fPrivateData, oldLength); memmove(fPrivateData + length, fPrivateData, oldLength);
if (string && length) if (string && length)
memcpy(fPrivateData, string, length); strncpy(fPrivateData, string, length);
return true; return true;
} }
return false; return false;
@@ -1848,7 +1858,7 @@ BString::_DoInsert(const char* string, int32 offset, int32 length)
memmove(fPrivateData + offset + length, fPrivateData + offset, memmove(fPrivateData + offset + length, fPrivateData + offset,
oldLength - offset); oldLength - offset);
if (string && length) if (string && length)
memcpy(fPrivateData + offset, string, length); strncpy(fPrivateData + offset, string, length);
return true; return true;
} }
return false; return false;