Bug 1340577 - Add release-grade assertions to various XPCOM string API implementations to avoid input causing an overflow. r=froydnj

--HG--
extra : rebase_source : af6aaf66863cb6a981a4d8f0deeac8e0f40278c1
This commit is contained in:
Honza Bambas 2017-02-21 11:38:00 -05:00
parent 6db3552e69
commit 7478e3a8b9
8 changed files with 122 additions and 69 deletions

View File

@ -1306,3 +1306,35 @@ ParseString(const nsACString& aSource, char aDelimiter,
return true;
}
const nsDependentSubstring
Substring(const char16_t* aStart, const char16_t* aEnd)
{
MOZ_RELEASE_ASSERT(aStart <= aEnd, "Overflow!");
MOZ_ASSERT(uint32_t(aEnd - aStart) == uintptr_t(aEnd - aStart),
"string too long");
return nsDependentSubstring(aStart, uint32_t(aEnd - aStart));
}
const nsDependentSubstring
StringTail(const nsAString& aStr, uint32_t aCount)
{
MOZ_RELEASE_ASSERT(aStr.Length() >= aCount, "Overflow!");
return nsDependentSubstring(aStr, aStr.Length() - aCount, aCount);
}
const nsDependentCSubstring
Substring(const char* aStart, const char* aEnd)
{
MOZ_RELEASE_ASSERT(aStart <= aEnd, "Overflow!");
MOZ_ASSERT(uint32_t(aEnd - aStart) == uintptr_t(aEnd - aStart),
"string too long");
return nsDependentCSubstring(aStart, uint32_t(aEnd - aStart));
}
inline const nsDependentCSubstring
StringTail(const nsACString& aStr, uint32_t aCount)
{
MOZ_RELEASE_ASSERT(aStr.Length() >= aCount, "Overflow!");
return nsDependentCSubstring(aStr, aStr.Length() - aCount, aCount);
}

View File

@ -1440,13 +1440,8 @@ Substring(const nsAString& aStr, uint32_t aStartPos, uint32_t aLength)
return nsDependentSubstring(aStr, aStartPos, aLength);
}
inline const nsDependentSubstring
Substring(const char16_t* aStart, const char16_t* aEnd)
{
MOZ_ASSERT(uint32_t(aEnd - aStart) == uintptr_t(aEnd - aStart),
"string too long");
return nsDependentSubstring(aStart, uint32_t(aEnd - aStart));
}
const nsDependentSubstring
Substring(const char16_t* aStart, const char16_t* aEnd);
inline const nsDependentSubstring
Substring(const char16_t* aStart, uint32_t aLength)
@ -1460,11 +1455,8 @@ StringHead(const nsAString& aStr, uint32_t aCount)
return nsDependentSubstring(aStr, 0, aCount);
}
inline const nsDependentSubstring
StringTail(const nsAString& aStr, uint32_t aCount)
{
return nsDependentSubstring(aStr, aStr.Length() - aCount, aCount);
}
const nsDependentSubstring
StringTail(const nsAString& aStr, uint32_t aCount);
// char
inline const nsDependentCSubstring
@ -1479,13 +1471,8 @@ Substring(const nsACString& aStr, uint32_t aStartPos, uint32_t aLength)
return nsDependentCSubstring(aStr, aStartPos, aLength);
}
inline const nsDependentCSubstring
Substring(const char* aStart, const char* aEnd)
{
MOZ_ASSERT(uint32_t(aEnd - aStart) == uintptr_t(aEnd - aStart),
"string too long");
return nsDependentCSubstring(aStart, uint32_t(aEnd - aStart));
}
const nsDependentCSubstring
Substring(const char* aStart, const char* aEnd);
inline const nsDependentCSubstring
Substring(const char* aStart, uint32_t aLength)
@ -1499,11 +1486,8 @@ StringHead(const nsACString& aStr, uint32_t aCount)
return nsDependentCSubstring(aStr, 0, aCount);
}
inline const nsDependentCSubstring
StringTail(const nsACString& aStr, uint32_t aCount)
{
return nsDependentCSubstring(aStr, aStr.Length() - aCount, aCount);
}
const nsDependentCSubstring
StringTail(const nsACString& aStr, uint32_t aCount);
inline bool

View File

@ -4,6 +4,15 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
nsTDependentString_CharT::nsTDependentString_CharT(const char_type* aStart,
const char_type* aEnd)
: string_type(const_cast<char_type*>(aStart),
uint32_t(aEnd - aStart), F_TERMINATED)
{
MOZ_RELEASE_ASSERT(aStart <= aEnd, "Overflow!");
AssertValidDependentString();
}
void
nsTDependentString_CharT::Rebind(const string_type& str, uint32_t startPos)
{
@ -23,3 +32,10 @@ nsTDependentString_CharT::Rebind(const string_type& str, uint32_t startPos)
SetDataFlags(str.Flags() & (F_TERMINATED | F_LITERAL));
}
void
nsTDependentString_CharT::Rebind(const char_type* aStart, const char_type* aEnd)
{
MOZ_RELEASE_ASSERT(aStart <= aEnd, "Overflow!");
Rebind(aStart, uint32_t(aEnd - aStart));
}

View File

@ -28,12 +28,7 @@ public:
* constructors
*/
nsTDependentString_CharT(const char_type* aStart, const char_type* aEnd)
: string_type(const_cast<char_type*>(aStart),
uint32_t(aEnd - aStart), F_TERMINATED)
{
AssertValidDependentString();
}
nsTDependentString_CharT(const char_type* aStart, const char_type* aEnd);
nsTDependentString_CharT(const char_type* aData, uint32_t aLength)
: string_type(const_cast<char_type*>(aData), aLength, F_TERMINATED)
@ -92,11 +87,7 @@ public:
Rebind(aData, uint32_t(char_traits::length(aData)));
}
void Rebind(const char_type* aStart, const char_type* aEnd)
{
Rebind(aStart, uint32_t(aEnd - aStart));
}
void Rebind(const char_type* aStart, const char_type* aEnd);
void Rebind(const string_type&, uint32_t aStartPos);
private:

View File

@ -35,3 +35,45 @@ nsTDependentSubstring_CharT::Rebind(const char_type* data, size_type length)
mLength = length;
SetDataFlags(F_NONE);
}
void
nsTDependentSubstring_CharT::Rebind(const char_type* aStart, const char_type* aEnd)
{
MOZ_RELEASE_ASSERT(aStart <= aEnd, "Overflow!");
Rebind(aStart, size_type(aEnd - aStart));
}
nsTDependentSubstring_CharT::nsTDependentSubstring_CharT(const char_type* aStart,
const char_type* aEnd)
: substring_type(const_cast<char_type*>(aStart), uint32_t(aEnd - aStart),
F_NONE)
{
MOZ_RELEASE_ASSERT(aStart <= aEnd, "Overflow!");
}
#if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
nsTDependentSubstring_CharT::nsTDependentSubstring_CharT(char16ptr_t aStart,
char16ptr_t aEnd)
: nsTDependentSubstring_CharT(static_cast<const char16_t*>(aStart),
static_cast<const char16_t*>(aEnd))
{
MOZ_RELEASE_ASSERT(static_cast<const char16_t*>(aStart) <=
static_cast<const char16_t*>(aEnd),
"Overflow!");
}
#endif
nsTDependentSubstring_CharT::nsTDependentSubstring_CharT(const const_iterator& aStart,
const const_iterator& aEnd)
: substring_type(const_cast<char_type*>(aStart.get()),
uint32_t(aEnd.get() - aStart.get()), F_NONE)
{
MOZ_RELEASE_ASSERT(aStart.get() <= aEnd.get(), "Overflow!");
}
const nsTDependentSubstring_CharT
Substring(const CharT* aStart, const CharT* aEnd)
{
MOZ_RELEASE_ASSERT(aStart <= aEnd, "Overflow!");
return nsTDependentSubstring_CharT(aStart, aEnd);
}

View File

@ -29,10 +29,7 @@ public:
void Rebind(const char_type* aData, size_type aLength);
void Rebind(const char_type* aStart, const char_type* aEnd)
{
Rebind(aStart, size_type(aEnd - aStart));
}
void Rebind(const char_type* aStart, const char_type* aEnd);
nsTDependentSubstring_CharT(const substring_type& aStr, uint32_t aStartPos,
uint32_t aLength = size_type(-1))
@ -46,11 +43,7 @@ public:
{
}
nsTDependentSubstring_CharT(const char_type* aStart, const char_type* aEnd)
: substring_type(const_cast<char_type*>(aStart), uint32_t(aEnd - aStart),
F_NONE)
{
}
nsTDependentSubstring_CharT(const char_type* aStart, const char_type* aEnd);
#if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
nsTDependentSubstring_CharT(char16ptr_t aData, size_type aLength)
@ -58,19 +51,11 @@ public:
{
}
nsTDependentSubstring_CharT(char16ptr_t aStart, char16ptr_t aEnd)
: nsTDependentSubstring_CharT(static_cast<const char16_t*>(aStart),
static_cast<const char16_t*>(aEnd))
{
}
nsTDependentSubstring_CharT(char16ptr_t aStart, char16ptr_t aEnd);
#endif
nsTDependentSubstring_CharT(const const_iterator& aStart,
const const_iterator& aEnd)
: substring_type(const_cast<char_type*>(aStart.get()),
uint32_t(aEnd.get() - aStart.get()), F_NONE)
{
}
const const_iterator& aEnd);
// Create a nsTDependentSubstring to be bound later
nsTDependentSubstring_CharT()
@ -105,11 +90,8 @@ Substring(const CharT* aData, uint32_t aLength)
return nsTDependentSubstring_CharT(aData, aLength);
}
inline const nsTDependentSubstring_CharT
Substring(const CharT* aStart, const CharT* aEnd)
{
return nsTDependentSubstring_CharT(aStart, aEnd);
}
const nsTDependentSubstring_CharT
Substring(const CharT* aStart, const CharT* aEnd);
inline const nsTDependentSubstring_CharT
StringHead(const nsTSubstring_CharT& aStr, uint32_t aCount)

View File

@ -35,6 +35,20 @@ AsFixedString(const nsTSubstring_CharT* aStr)
}
nsTSubstring_CharT::char_type
nsTSubstring_CharT::First() const
{
MOZ_RELEASE_ASSERT(mLength > 0, "|First()| called on an empty string");
return mData[0];
}
nsTSubstring_CharT::char_type
nsTSubstring_CharT::Last() const
{
MOZ_RELEASE_ASSERT(mLength > 0, "|Last()| called on an empty string");
return mData[mLength - 1];
}
/**
* this function is called to prepare mData for writing. the given capacity
* indicates the required minimum storage size for mData, in sizeof(char_type)

View File

@ -272,17 +272,9 @@ public:
return CharAt(aIndex);
}
char_type First() const
{
NS_ASSERTION(mLength > 0, "|First()| called on an empty string");
return mData[0];
}
char_type First() const;
inline char_type Last() const
{
NS_ASSERTION(mLength > 0, "|Last()| called on an empty string");
return mData[mLength - 1];
}
char_type Last() const;
size_type NS_FASTCALL CountChar(char_type) const;
int32_t NS_FASTCALL FindChar(char_type, index_type aOffset = 0) const;