From 7b521af105367cb0578e878a50b0bf02d6dd8451 Mon Sep 17 00:00:00 2001 From: "vitalyr@chromium.org" Date: Tue, 6 Jul 2010 12:22:19 +0000 Subject: [PATCH] Fix crash: handle all flat string types in regexp replace. Review URL: http://codereview.chromium.org/2868046 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5025 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/objects.h | 8 +++++ src/runtime.cc | 18 +++++----- test/mjsunit/string-replace-with-empty.js | 57 +++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 10 deletions(-) create mode 100644 test/mjsunit/string-replace-with-empty.js diff --git a/src/objects.h b/src/objects.h index dc59d57..4a7dee6 100644 --- a/src/objects.h +++ b/src/objects.h @@ -4413,6 +4413,8 @@ class SeqString: public String { // Each character in the AsciiString is an ascii character. class SeqAsciiString: public SeqString { public: + static const bool kHasAsciiEncoding = true; + // Dispatched behavior. inline uint16_t SeqAsciiStringGet(int index); inline void SeqAsciiStringSet(int index, uint16_t value); @@ -4462,6 +4464,8 @@ class SeqAsciiString: public SeqString { // Each character in the TwoByteString is a two-byte uint16_t. class SeqTwoByteString: public SeqString { public: + static const bool kHasAsciiEncoding = false; + // Dispatched behavior. inline uint16_t SeqTwoByteStringGet(int index); inline void SeqTwoByteStringSet(int index, uint16_t value); @@ -4594,6 +4598,8 @@ class ExternalString: public String { // ASCII string. class ExternalAsciiString: public ExternalString { public: + static const bool kHasAsciiEncoding = true; + typedef v8::String::ExternalAsciiStringResource Resource; // The underlying resource. @@ -4626,6 +4632,8 @@ class ExternalAsciiString: public ExternalString { // encoded string. class ExternalTwoByteString: public ExternalString { public: + static const bool kHasAsciiEncoding = false; + typedef v8::String::ExternalStringResource Resource; // The underlying string resource. diff --git a/src/runtime.cc b/src/runtime.cc index e3a150d..157d086 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -2284,8 +2284,9 @@ static Object* StringReplaceRegExpWithString(String* subject, return *(builder.ToString()); } + template -static Object* StringReplaceRegExpWithEmptyString(ResultSeqString* subject, +static Object* StringReplaceRegExpWithEmptyString(String* subject, JSRegExp* regexp, JSArray* last_match_info) { ASSERT(subject->IsFlat()); @@ -2320,9 +2321,8 @@ static Object* StringReplaceRegExpWithEmptyString(ResultSeqString* subject, if (new_length == 0) { return Heap::empty_string(); } - // TODO(sandholm) try to use types statically to determine this. Handle answer; - if (subject_handle->IsAsciiRepresentation()) { + if (ResultSeqString::kHasAsciiEncoding) { answer = Handle::cast(Factory::NewRawAsciiString(new_length)); } else { @@ -2440,14 +2440,12 @@ static Object* Runtime_StringReplaceRegExpWithString(Arguments args) { ASSERT(last_match_info->HasFastElements()); if (replacement->length() == 0) { - if (subject->IsAsciiRepresentation()) { - return StringReplaceRegExpWithEmptyString(SeqAsciiString::cast(subject), - regexp, - last_match_info); + if (subject->HasOnlyAsciiChars()) { + return StringReplaceRegExpWithEmptyString( + subject, regexp, last_match_info); } else { - return StringReplaceRegExpWithEmptyString(SeqTwoByteString::cast(subject), - regexp, - last_match_info); + return StringReplaceRegExpWithEmptyString( + subject, regexp, last_match_info); } } diff --git a/test/mjsunit/string-replace-with-empty.js b/test/mjsunit/string-replace-with-empty.js new file mode 100644 index 0000000..0e1e70a --- /dev/null +++ b/test/mjsunit/string-replace-with-empty.js @@ -0,0 +1,57 @@ +// Copyright 2010 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --expose-externalize-string + +assertEquals("0123", "aa0bb1cc2dd3".replace(/[a-z]/g, "")); +assertEquals("0123", "\u1234a0bb1cc2dd3".replace(/[\u1234a-z]/g, "")); + +var expected = "0123"; +var cons = "a0b1c2d3"; +for (var i = 0; i < 5; i++) { + expected += expected; + cons += cons; +} +assertEquals(expected, cons.replace(/[a-z]/g, "")); +cons = "\u12340b1c2d3"; +for (var i = 0; i < 5; i++) { + cons += cons; +} +assertEquals(expected, cons.replace(/[\u1234a-z]/g, "")); + +cons = "a0b1c2d3"; +for (var i = 0; i < 5; i++) { + cons += cons; +} +externalizeString(cons, true/* force two-byte */); +assertEquals(expected, cons.replace(/[a-z]/g, "")); +cons = "\u12340b1c2d3"; +for (var i = 0; i < 5; i++) { + cons += cons; +} +externalizeString(cons); +assertEquals(expected, cons.replace(/[\u1234a-z]/g, "")); -- 2.7.4