From 3fd15a87ada28cd7eb9b23d9d2f55999e65cd5f8 Mon Sep 17 00:00:00 2001 From: Cameron Kaiser Date: Sat, 17 Aug 2019 10:42:19 -0700 Subject: [PATCH] #565: M1358297 parts 3 and 4 --- docshell/base/nsDefaultURIFixup.cpp | 2 +- docshell/base/nsDocShell.cpp | 2 +- dom/base/nsContentUtils.cpp | 4 +- dom/html/HTMLInputElement.cpp | 6 +-- editor/libeditor/nsTextEditRules.cpp | 2 +- netwerk/mime/nsMIMEHeaderParamImpl.cpp | 4 +- xpcom/string/nsStringObsolete.cpp | 2 - xpcom/string/nsTString.h | 4 +- xpcom/string/nsTStringObsolete.cpp | 68 +++++++++++++++++++++++--- xpcom/string/nsTSubstring.cpp | 44 ++++++++++++++++- xpcom/string/nsTSubstring.h | 26 ++++++++++ xpfe/appshell/nsXULWindow.cpp | 2 +- 12 files changed, 141 insertions(+), 25 deletions(-) diff --git a/docshell/base/nsDefaultURIFixup.cpp b/docshell/base/nsDefaultURIFixup.cpp index 9d4d03a93..be8b5dd2b 100644 --- a/docshell/base/nsDefaultURIFixup.cpp +++ b/docshell/base/nsDefaultURIFixup.cpp @@ -167,7 +167,7 @@ nsDefaultURIFixup::GetFixupURIInfo(const nsACString& aStringURI, nsAutoCString uriString(aStringURI); // Eliminate embedded newlines, which single-line text fields now allow: - uriString.StripChars("\r\n"); + uriString.StripCRLF(); // Cleanup the empty spaces that might be on each end: uriString.Trim(" "); diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index b18e1d4b2..58a091739 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -4616,7 +4616,7 @@ nsDocShell::LoadURIWithOptions(const char16_t* aURI, // Cleanup the empty spaces that might be on each end. uriString.Trim(" "); // Eliminate embedded newlines, which single-line text fields now allow: - uriString.StripChars("\r\n"); + uriString.StripCRLF(); NS_ENSURE_TRUE(!uriString.IsEmpty(), NS_ERROR_FAILURE); rv = NS_NewURI(getter_AddRefs(uri), uriString); diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index 20ab3ef78..12e7ee479 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -6406,9 +6406,7 @@ nsContentUtils::FlushLayoutForTree(nsIDOMWindow* aWindow) void nsContentUtils::RemoveNewlines(nsString &aString) { - // strip CR/LF and null - static const char badChars[] = {'\r', '\n', 0}; - aString.StripChars(badChars); + aString.StripCRLF(); } void diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp index 4b227038e..7a689ce63 100644 --- a/dom/html/HTMLInputElement.cpp +++ b/dom/html/HTMLInputElement.cpp @@ -4773,15 +4773,13 @@ HTMLInputElement::SanitizeValue(nsAString& aValue) case NS_FORM_INPUT_TEL: case NS_FORM_INPUT_PASSWORD: { - char16_t crlf[] = { char16_t('\r'), char16_t('\n'), 0 }; - aValue.StripChars(crlf); + aValue.StripCRLF(); } break; case NS_FORM_INPUT_EMAIL: case NS_FORM_INPUT_URL: { - char16_t crlf[] = { char16_t('\r'), char16_t('\n'), 0 }; - aValue.StripChars(crlf); + aValue.StripCRLF(); aValue = nsContentUtils::TrimWhitespace(aValue); } diff --git a/editor/libeditor/nsTextEditRules.cpp b/editor/libeditor/nsTextEditRules.cpp index 788f1f2a7..beab264b8 100644 --- a/editor/libeditor/nsTextEditRules.cpp +++ b/editor/libeditor/nsTextEditRules.cpp @@ -527,7 +527,7 @@ nsTextEditRules::HandleNewLines(nsString &aString, aString.ReplaceChar(CRLF, ' '); break; case nsIPlaintextEditor::eNewlinesStrip: - aString.StripChars(CRLF); + aString.StripCRLF(); break; case nsIPlaintextEditor::eNewlinesPasteToFirst: default: diff --git a/netwerk/mime/nsMIMEHeaderParamImpl.cpp b/netwerk/mime/nsMIMEHeaderParamImpl.cpp index 0a73a00a6..462496918 100644 --- a/netwerk/mime/nsMIMEHeaderParamImpl.cpp +++ b/netwerk/mime/nsMIMEHeaderParamImpl.cpp @@ -521,7 +521,7 @@ nsMIMEHeaderParamImpl::DoParameterInternal(const char *aHeaderValue, // if the parameter spans across multiple lines we have to strip out the // line continuation -- jht 4/29/98 nsAutoCString tempStr(valueStart, valueEnd - valueStart); - tempStr.StripChars("\r\n"); + tempStr.StripCRLF(); char *res = ToNewCString(tempStr); NS_ENSURE_TRUE(res, NS_ERROR_OUT_OF_MEMORY); @@ -764,7 +764,7 @@ internalDecodeRFC2047Header(const char* aHeaderVal, const char* aDefaultCharset, nsAutoCString temp(aResult); temp.ReplaceSubstring("\n\t", " "); temp.ReplaceSubstring("\r\t", " "); - temp.StripChars("\r\n"); + temp.StripCRLF(); aResult = temp; } diff --git a/xpcom/string/nsStringObsolete.cpp b/xpcom/string/nsStringObsolete.cpp index bd6daacab..2cfe06be3 100644 --- a/xpcom/string/nsStringObsolete.cpp +++ b/xpcom/string/nsStringObsolete.cpp @@ -540,8 +540,6 @@ StripChars2(char16_t* aString,uint32_t aLength,const char* aSet) { /* ***** END RICKG BLOCK ***** */ -static const char* kWhitespace="\f\t\r\n "; - // This function is used to implement FindCharInSet and friends template #ifndef __SUNPRO_CC diff --git a/xpcom/string/nsTString.h b/xpcom/string/nsTString.h index 93f39d20c..f51730ba4 100644 --- a/xpcom/string/nsTString.h +++ b/xpcom/string/nsTString.h @@ -369,13 +369,13 @@ public: * @param aSet -- characters to be cut from this */ void StripChars(const char* aSet); - + bool StripChars(const char* aSet, const fallible_t&); /** * This method strips whitespace throughout the string. */ void StripWhitespace(); - + bool StripWhitespace(const fallible_t&); /** * swaps occurence of 1 string for another diff --git a/xpcom/string/nsTStringObsolete.cpp b/xpcom/string/nsTStringObsolete.cpp index df4dec296..be4f687cf 100644 --- a/xpcom/string/nsTStringObsolete.cpp +++ b/xpcom/string/nsTStringObsolete.cpp @@ -5,6 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsTArray.h" +#include "nsASCIIMask.h" /** * nsTString::Find @@ -400,18 +401,40 @@ nsTString_CharT::SetCharAt( char16_t aChar, uint32_t aIndex ) void nsTString_CharT::StripChars( const char* aSet ) { - if (!EnsureMutable()) + if (!StripChars(aSet, mozilla::fallible)) { AllocFailed(mLength); + } +} + +bool +nsTString_CharT::StripChars( const char* aSet, const fallible_t& ) +{ + if (!EnsureMutable()) { + return false; + } mLength = nsBufferRoutines::strip_chars(mData, mLength, aSet); + return true; } void nsTString_CharT::StripWhitespace() { - StripChars(kWhitespace); + if (!StripWhitespace(mozilla::fallible)) { + AllocFailed(mLength); + } } +bool +nsTString_CharT::StripWhitespace( const fallible_t& ) +{ + if (!EnsureMutable()) { + return false; + } + + StripTaggedASCII(mozilla::ASCIIMask::MaskWhitespace()); + return true; +} /** * nsTString::ReplaceChar,ReplaceSubstring @@ -651,13 +674,44 @@ nsTString_CharT::Trim( const char* aSet, bool aTrimLeading, bool aTrimTrailing, void nsTString_CharT::CompressWhitespace( bool aTrimLeading, bool aTrimTrailing ) { - const char* set = kWhitespace; + // Quick exit + if (mLength == 0) { + return; + } - ReplaceChar(set, ' '); - Trim(set, aTrimLeading, aTrimTrailing); + if (!EnsureMutable()) + AllocFailed(mLength); - // this one does some questionable fu... just copying the old code! - mLength = nsBufferRoutines::compress_chars(mData, mLength, set); + const ASCIIMaskArray& mask = mozilla::ASCIIMask::MaskWhitespace(); + + char_type* to = mData; + char_type* from = mData; + char_type* end = mData + mLength; + + // Compresses runs of whitespace down to a normal space ' ' and convert + // any whitespace to a normal space. This assumes that whitespace is + // all standard 7-bit ASCII. + bool skipWS = aTrimLeading; + while (from < end) { + uint32_t theChar = *from++; + if (mozilla::ASCIIMask::IsMasked(mask, theChar)) { + if (!skipWS) { + *to++ = ' '; + skipWS = true; + } + } else { + *to++ = theChar; + skipWS = false; + } + } + + // If we need to trim the trailing whitespace, back up one character. + if (aTrimTrailing && skipWS && to > mData) { + to--; + } + + *to = char_type(0); // add the null + mLength = to - mData; } diff --git a/xpcom/string/nsTSubstring.cpp b/xpcom/string/nsTSubstring.cpp index 54d687b66..7a4f56046 100644 --- a/xpcom/string/nsTSubstring.cpp +++ b/xpcom/string/nsTSubstring.cpp @@ -4,6 +4,7 @@ * 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/. */ +#include "nsASCIIMask.h" #include "mozilla/CheckedInt.h" #include "mozilla/double-conversion.h" #include "mozilla/MemoryReporting.h" @@ -821,7 +822,8 @@ nsTSubstring_CharT::FindChar(char_type aChar, index_type aOffset) const void nsTSubstring_CharT::StripChar(char_type aChar, int32_t aOffset) { - if (mLength == 0 || aOffset >= int32_t(mLength)) { + // Note that this implicitly guarantees mLength > 0 + if (aOffset >= int32_t(mLength)) { return; } @@ -848,6 +850,7 @@ nsTSubstring_CharT::StripChar(char_type aChar, int32_t aOffset) void nsTSubstring_CharT::StripChars(const char_type* aChars, uint32_t aOffset) { + // Note that this implicitly guarantees mLength > 0 if (aOffset >= uint32_t(mLength)) { return; } @@ -877,6 +880,45 @@ nsTSubstring_CharT::StripChars(const char_type* aChars, uint32_t aOffset) mLength = to - mData; } +void +nsTSubstring_CharT::StripTaggedASCII(const ASCIIMaskArray& aToStrip, + uint32_t aOffset) +{ + // Note that this implicitly guarantees mLength > 0 + if (aOffset >= uint32_t(mLength)) { + return; + } + + if (!EnsureMutable()) { + AllocFailed(mLength); + } + + char_type* to = mData + aOffset; + char_type* from = mData + aOffset; + char_type* end = mData + mLength; + + while (from < end) { + uint32_t theChar = (uint32_t)*from++; + // Replacing this with a call to ASCIIMask::IsMasked + // regresses performance somewhat, so leaving it inlined. + if (!mozilla::ASCIIMask::IsMasked(aToStrip, theChar)) { + // Not stripped, copy this char. + *to++ = (char_type)theChar; + } + } + *to = char_type(0); // add the null + mLength = to - mData; +} + +void +nsTSubstring_CharT::StripCRLF(uint32_t aOffset) +{ + // Expanding this call to copy the code from StripTaggedASCII + // instead of just calling it does somewhat help with performance + // but it is not worth it given the duplicated code. + StripTaggedASCII(mozilla::ASCIIMask::MaskCRLF(), aOffset); +} + int nsTSubstring_CharT::AppendFunc(void* aArg, const char* aStr, uint32_t aLen) { diff --git a/xpcom/string/nsTSubstring.h b/xpcom/string/nsTSubstring.h index fb6328a3f..174375a2a 100644 --- a/xpcom/string/nsTSubstring.h +++ b/xpcom/string/nsTSubstring.h @@ -5,6 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // IWYU pragma: private, include "nsString.h" +#include #include "mozilla/Casting.h" #include "mozilla/MemoryReporting.h" @@ -833,6 +834,31 @@ public: void StripChars(const char_type* aChars, uint32_t aOffset = 0); + /** + * This method is used to remove all occurrences of some characters this + * from this string. The characters removed have the corresponding + * entries in the bool array set to true; we retain all characters + * with code beyond 127. + * THE CALLER IS RESPONSIBLE for making sure the complete boolean + * array, 128 entries, is properly initialized. + * + * See also: ASCIIMask class. + * + * @param aToStrip -- Array where each entry is true if the + * corresponding ASCII character is to be stripped. All + * characters beyond code 127 are retained. Note that this + * parameter is of ASCIIMaskArray type, but we expand the typedef + * to avoid having to include nsASCIIMask.h in this include file + * as it brings other includes. + * @param aOffset -- where in this string to start stripping chars + */ + void StripTaggedASCII(const std::array& aToStrip, uint32_t aOffset = 0); + + /** + * A shortcut to strip \r and \n. + */ + void StripCRLF(uint32_t aOffset = 0); + /** * If the string uses a shared buffer, this method * clears the pointer without releasing the buffer. diff --git a/xpfe/appshell/nsXULWindow.cpp b/xpfe/appshell/nsXULWindow.cpp index ac20eca60..40529a072 100644 --- a/xpfe/appshell/nsXULWindow.cpp +++ b/xpfe/appshell/nsXULWindow.cpp @@ -917,7 +917,7 @@ NS_IMETHODIMP nsXULWindow::SetTitle(const char16_t* aTitle) { NS_ENSURE_STATE(mWindow); mTitle.Assign(aTitle); - mTitle.StripChars("\n\r"); + mTitle.StripCRLF(); NS_ENSURE_SUCCESS(mWindow->SetTitle(mTitle), NS_ERROR_FAILURE); // Tell the window mediator that a title has changed