v8  3.14.5(node0.10.28)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
test-strings.cc
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 
3 // Check that we can traverse very deep stacks of ConsStrings using
4 // StringInputBuffer. Check that Get(int) works on very deep stacks
5 // of ConsStrings. These operations may not be very fast, but they
6 // should be possible without getting errors due to too deep recursion.
7 
8 #include <stdlib.h>
9 
10 #include "v8.h"
11 
12 #include "api.h"
13 #include "factory.h"
14 #include "objects.h"
15 #include "cctest.h"
16 #include "zone-inl.h"
17 
18 unsigned int seed = 123;
19 
20 static uint32_t gen() {
21  uint64_t z;
22  z = seed;
23  z *= 279470273;
24  z %= 4294967291U;
25  seed = static_cast<unsigned int>(z);
26  return static_cast<uint32_t>(seed >> 16);
27 }
28 
29 
30 using namespace v8::internal;
31 
33 
34 
35 static void InitializeVM() {
36  if (env.IsEmpty()) {
37  v8::HandleScope scope;
38  const char* extensions[] = { "v8/print" };
39  v8::ExtensionConfiguration config(1, extensions);
40  env = v8::Context::New(&config);
41  }
42  v8::HandleScope scope;
43  env->Enter();
44 }
45 
46 
47 static const int NUMBER_OF_BUILDING_BLOCKS = 128;
48 static const int DEEP_DEPTH = 8 * 1024;
49 static const int SUPER_DEEP_DEPTH = 80 * 1024;
50 
51 
53  public ZoneObject {
54  public:
55  explicit Resource(Vector<const uc16> string): data_(string.start()) {
56  length_ = string.length();
57  }
58  virtual const uint16_t* data() const { return data_; }
59  virtual size_t length() const { return length_; }
60 
61  private:
62  const uc16* data_;
63  size_t length_;
64 };
65 
66 
68  public ZoneObject {
69  public:
70  explicit AsciiResource(Vector<const char> string): data_(string.start()) {
71  length_ = string.length();
72  }
73  virtual const char* data() const { return data_; }
74  virtual size_t length() const { return length_; }
75 
76  private:
77  const char* data_;
78  size_t length_;
79 };
80 
81 
82 static void InitializeBuildingBlocks(
83  Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS]) {
84  // A list of pointers that we don't have any interest in cleaning up.
85  // If they are reachable from a root then leak detection won't complain.
86  Zone* zone = Isolate::Current()->runtime_zone();
87  for (int i = 0; i < NUMBER_OF_BUILDING_BLOCKS; i++) {
88  int len = gen() % 16;
89  if (len > 14) {
90  len += 1234;
91  }
92  switch (gen() % 4) {
93  case 0: {
94  uc16 buf[2000];
95  for (int j = 0; j < len; j++) {
96  buf[j] = gen() % 65536;
97  }
98  building_blocks[i] =
99  FACTORY->NewStringFromTwoByte(Vector<const uc16>(buf, len));
100  for (int j = 0; j < len; j++) {
101  CHECK_EQ(buf[j], building_blocks[i]->Get(j));
102  }
103  break;
104  }
105  case 1: {
106  char buf[2000];
107  for (int j = 0; j < len; j++) {
108  buf[j] = gen() % 128;
109  }
110  building_blocks[i] =
111  FACTORY->NewStringFromAscii(Vector<const char>(buf, len));
112  for (int j = 0; j < len; j++) {
113  CHECK_EQ(buf[j], building_blocks[i]->Get(j));
114  }
115  break;
116  }
117  case 2: {
118  uc16* buf = zone->NewArray<uc16>(len);
119  for (int j = 0; j < len; j++) {
120  buf[j] = gen() % 65536;
121  }
122  Resource* resource = new(zone) Resource(Vector<const uc16>(buf, len));
123  building_blocks[i] = FACTORY->NewExternalStringFromTwoByte(resource);
124  for (int j = 0; j < len; j++) {
125  CHECK_EQ(buf[j], building_blocks[i]->Get(j));
126  }
127  break;
128  }
129  case 3: {
130  char* buf = NewArray<char>(len);
131  for (int j = 0; j < len; j++) {
132  buf[j] = gen() % 128;
133  }
134  building_blocks[i] =
135  FACTORY->NewStringFromAscii(Vector<const char>(buf, len));
136  for (int j = 0; j < len; j++) {
137  CHECK_EQ(buf[j], building_blocks[i]->Get(j));
138  }
139  DeleteArray<char>(buf);
140  break;
141  }
142  }
143  }
144 }
145 
146 
147 static Handle<String> ConstructLeft(
148  Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS],
149  int depth) {
150  Handle<String> answer = FACTORY->NewStringFromAscii(CStrVector(""));
151  for (int i = 0; i < depth; i++) {
152  answer = FACTORY->NewConsString(
153  answer,
154  building_blocks[i % NUMBER_OF_BUILDING_BLOCKS]);
155  }
156  return answer;
157 }
158 
159 
160 static Handle<String> ConstructRight(
161  Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS],
162  int depth) {
163  Handle<String> answer = FACTORY->NewStringFromAscii(CStrVector(""));
164  for (int i = depth - 1; i >= 0; i--) {
165  answer = FACTORY->NewConsString(
166  building_blocks[i % NUMBER_OF_BUILDING_BLOCKS],
167  answer);
168  }
169  return answer;
170 }
171 
172 
173 static Handle<String> ConstructBalancedHelper(
174  Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS],
175  int from,
176  int to) {
177  CHECK(to > from);
178  if (to - from == 1) {
179  return building_blocks[from % NUMBER_OF_BUILDING_BLOCKS];
180  }
181  if (to - from == 2) {
182  return FACTORY->NewConsString(
183  building_blocks[from % NUMBER_OF_BUILDING_BLOCKS],
184  building_blocks[(from+1) % NUMBER_OF_BUILDING_BLOCKS]);
185  }
186  Handle<String> part1 =
187  ConstructBalancedHelper(building_blocks, from, from + ((to - from) / 2));
188  Handle<String> part2 =
189  ConstructBalancedHelper(building_blocks, from + ((to - from) / 2), to);
190  return FACTORY->NewConsString(part1, part2);
191 }
192 
193 
194 static Handle<String> ConstructBalanced(
195  Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS]) {
196  return ConstructBalancedHelper(building_blocks, 0, DEEP_DEPTH);
197 }
198 
199 
200 static StringInputBuffer buffer;
201 
202 
203 static void Traverse(Handle<String> s1, Handle<String> s2) {
204  int i = 0;
205  buffer.Reset(*s1);
206  StringInputBuffer buffer2(*s2);
207  while (buffer.has_more()) {
208  CHECK(buffer2.has_more());
209  uint16_t c = buffer.GetNext();
210  CHECK_EQ(c, buffer2.GetNext());
211  i++;
212  }
213  CHECK_EQ(s1->length(), i);
214  CHECK_EQ(s2->length(), i);
215 }
216 
217 
218 static void TraverseFirst(Handle<String> s1, Handle<String> s2, int chars) {
219  int i = 0;
220  buffer.Reset(*s1);
221  StringInputBuffer buffer2(*s2);
222  while (buffer.has_more() && i < chars) {
223  CHECK(buffer2.has_more());
224  uint16_t c = buffer.GetNext();
225  CHECK_EQ(c, buffer2.GetNext());
226  i++;
227  }
228  s1->Get(s1->length() - 1);
229  s2->Get(s2->length() - 1);
230 }
231 
232 
233 TEST(Traverse) {
234  printf("TestTraverse\n");
235  InitializeVM();
236  v8::HandleScope scope;
237  Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS];
238  ZoneScope zone(Isolate::Current()->runtime_zone(), DELETE_ON_EXIT);
239  InitializeBuildingBlocks(building_blocks);
240  Handle<String> flat = ConstructBalanced(building_blocks);
241  FlattenString(flat);
242  Handle<String> left_asymmetric = ConstructLeft(building_blocks, DEEP_DEPTH);
243  Handle<String> right_asymmetric = ConstructRight(building_blocks, DEEP_DEPTH);
244  Handle<String> symmetric = ConstructBalanced(building_blocks);
245  printf("1\n");
246  Traverse(flat, symmetric);
247  printf("2\n");
248  Traverse(flat, left_asymmetric);
249  printf("3\n");
250  Traverse(flat, right_asymmetric);
251  printf("4\n");
252  Handle<String> left_deep_asymmetric =
253  ConstructLeft(building_blocks, SUPER_DEEP_DEPTH);
254  Handle<String> right_deep_asymmetric =
255  ConstructRight(building_blocks, SUPER_DEEP_DEPTH);
256  printf("5\n");
257  TraverseFirst(left_asymmetric, left_deep_asymmetric, 1050);
258  printf("6\n");
259  TraverseFirst(left_asymmetric, right_deep_asymmetric, 65536);
260  printf("7\n");
261  FlattenString(left_asymmetric);
262  printf("10\n");
263  Traverse(flat, left_asymmetric);
264  printf("11\n");
265  FlattenString(right_asymmetric);
266  printf("12\n");
267  Traverse(flat, right_asymmetric);
268  printf("14\n");
269  FlattenString(symmetric);
270  printf("15\n");
271  Traverse(flat, symmetric);
272  printf("16\n");
273  FlattenString(left_deep_asymmetric);
274  printf("18\n");
275 }
276 
277 
278 static const int DEEP_ASCII_DEPTH = 100000;
279 
280 
281 TEST(DeepAscii) {
282  printf("TestDeepAscii\n");
283  InitializeVM();
284  v8::HandleScope scope;
285 
286  char* foo = NewArray<char>(DEEP_ASCII_DEPTH);
287  for (int i = 0; i < DEEP_ASCII_DEPTH; i++) {
288  foo[i] = "foo "[i % 4];
289  }
290  Handle<String> string =
291  FACTORY->NewStringFromAscii(Vector<const char>(foo, DEEP_ASCII_DEPTH));
292  Handle<String> foo_string = FACTORY->NewStringFromAscii(CStrVector("foo"));
293  for (int i = 0; i < DEEP_ASCII_DEPTH; i += 10) {
294  string = FACTORY->NewConsString(string, foo_string);
295  }
296  Handle<String> flat_string = FACTORY->NewConsString(string, foo_string);
297  FlattenString(flat_string);
298 
299  for (int i = 0; i < 500; i++) {
300  TraverseFirst(flat_string, string, DEEP_ASCII_DEPTH);
301  }
302  DeleteArray<char>(foo);
303 }
304 
305 
306 TEST(Utf8Conversion) {
307  // Smoke test for converting strings to utf-8.
308  InitializeVM();
309  v8::HandleScope handle_scope;
310  // A simple ascii string
311  const char* ascii_string = "abcdef12345";
312  int len =
313  v8::String::New(ascii_string,
314  StrLength(ascii_string))->Utf8Length();
315  CHECK_EQ(StrLength(ascii_string), len);
316  // A mixed ascii and non-ascii string
317  // U+02E4 -> CB A4
318  // U+0064 -> 64
319  // U+12E4 -> E1 8B A4
320  // U+0030 -> 30
321  // U+3045 -> E3 81 85
322  const uint16_t mixed_string[] = {0x02E4, 0x0064, 0x12E4, 0x0030, 0x3045};
323  // The characters we expect to be output
324  const unsigned char as_utf8[11] = {0xCB, 0xA4, 0x64, 0xE1, 0x8B, 0xA4, 0x30,
325  0xE3, 0x81, 0x85, 0x00};
326  // The number of bytes expected to be written for each length
327  const int lengths[12] = {0, 0, 2, 3, 3, 3, 6, 7, 7, 7, 10, 11};
328  const int char_lengths[12] = {0, 0, 1, 2, 2, 2, 3, 4, 4, 4, 5, 5};
329  v8::Handle<v8::String> mixed = v8::String::New(mixed_string, 5);
330  CHECK_EQ(10, mixed->Utf8Length());
331  // Try encoding the string with all capacities
332  char buffer[11];
333  const char kNoChar = static_cast<char>(-1);
334  for (int i = 0; i <= 11; i++) {
335  // Clear the buffer before reusing it
336  for (int j = 0; j < 11; j++)
337  buffer[j] = kNoChar;
338  int chars_written;
339  int written = mixed->WriteUtf8(buffer, i, &chars_written);
340  CHECK_EQ(lengths[i], written);
341  CHECK_EQ(char_lengths[i], chars_written);
342  // Check that the contents are correct
343  for (int j = 0; j < lengths[i]; j++)
344  CHECK_EQ(as_utf8[j], static_cast<unsigned char>(buffer[j]));
345  // Check that the rest of the buffer hasn't been touched
346  for (int j = lengths[i]; j < 11; j++)
347  CHECK_EQ(kNoChar, buffer[j]);
348  }
349 }
350 
351 
352 TEST(ExternalShortStringAdd) {
353  ZoneScope zonescope(Isolate::Current()->runtime_zone(), DELETE_ON_EXIT);
354 
355  InitializeVM();
356  v8::HandleScope handle_scope;
357  Zone* zone = Isolate::Current()->runtime_zone();
358 
359  // Make sure we cover all always-flat lengths and at least one above.
360  static const int kMaxLength = 20;
361  CHECK_GT(kMaxLength, i::ConsString::kMinLength);
362 
363  // Allocate two JavaScript arrays for holding short strings.
364  v8::Handle<v8::Array> ascii_external_strings =
365  v8::Array::New(kMaxLength + 1);
366  v8::Handle<v8::Array> non_ascii_external_strings =
367  v8::Array::New(kMaxLength + 1);
368 
369  // Generate short ascii and non-ascii external strings.
370  for (int i = 0; i <= kMaxLength; i++) {
371  char* ascii = zone->NewArray<char>(i + 1);
372  for (int j = 0; j < i; j++) {
373  ascii[j] = 'a';
374  }
375  // Terminating '\0' is left out on purpose. It is not required for external
376  // string data.
377  AsciiResource* ascii_resource =
378  new(zone) AsciiResource(Vector<const char>(ascii, i));
379  v8::Local<v8::String> ascii_external_string =
380  v8::String::NewExternal(ascii_resource);
381 
382  ascii_external_strings->Set(v8::Integer::New(i), ascii_external_string);
383  uc16* non_ascii = zone->NewArray<uc16>(i + 1);
384  for (int j = 0; j < i; j++) {
385  non_ascii[j] = 0x1234;
386  }
387  // Terminating '\0' is left out on purpose. It is not required for external
388  // string data.
389  Resource* resource = new(zone) Resource(Vector<const uc16>(non_ascii, i));
390  v8::Local<v8::String> non_ascii_external_string =
391  v8::String::NewExternal(resource);
392  non_ascii_external_strings->Set(v8::Integer::New(i),
393  non_ascii_external_string);
394  }
395 
396  // Add the arrays with the short external strings in the global object.
397  v8::Handle<v8::Object> global = env->Global();
398  global->Set(v8_str("external_ascii"), ascii_external_strings);
399  global->Set(v8_str("external_non_ascii"), non_ascii_external_strings);
400  global->Set(v8_str("max_length"), v8::Integer::New(kMaxLength));
401 
402  // Add short external ascii and non-ascii strings checking the result.
403  static const char* source =
404  "function test() {"
405  " var ascii_chars = 'aaaaaaaaaaaaaaaaaaaa';"
406  " var non_ascii_chars = '\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234';" //NOLINT
407  " if (ascii_chars.length != max_length) return 1;"
408  " if (non_ascii_chars.length != max_length) return 2;"
409  " var ascii = Array(max_length + 1);"
410  " var non_ascii = Array(max_length + 1);"
411  " for (var i = 0; i <= max_length; i++) {"
412  " ascii[i] = ascii_chars.substring(0, i);"
413  " non_ascii[i] = non_ascii_chars.substring(0, i);"
414  " };"
415  " for (var i = 0; i <= max_length; i++) {"
416  " if (ascii[i] != external_ascii[i]) return 3;"
417  " if (non_ascii[i] != external_non_ascii[i]) return 4;"
418  " for (var j = 0; j < i; j++) {"
419  " if (external_ascii[i] !="
420  " (external_ascii[j] + external_ascii[i - j])) return 5;"
421  " if (external_non_ascii[i] !="
422  " (external_non_ascii[j] + external_non_ascii[i - j])) return 6;"
423  " if (non_ascii[i] != (non_ascii[j] + non_ascii[i - j])) return 7;"
424  " if (ascii[i] != (ascii[j] + ascii[i - j])) return 8;"
425  " if (ascii[i] != (external_ascii[j] + ascii[i - j])) return 9;"
426  " if (ascii[i] != (ascii[j] + external_ascii[i - j])) return 10;"
427  " if (non_ascii[i] !="
428  " (external_non_ascii[j] + non_ascii[i - j])) return 11;"
429  " if (non_ascii[i] !="
430  " (non_ascii[j] + external_non_ascii[i - j])) return 12;"
431  " }"
432  " }"
433  " return 0;"
434  "};"
435  "test()";
436  CHECK_EQ(0, CompileRun(source)->Int32Value());
437 }
438 
439 
440 TEST(CachedHashOverflow) {
441  // We incorrectly allowed strings to be tagged as array indices even if their
442  // values didn't fit in the hash field.
443  // See http://code.google.com/p/v8/issues/detail?id=728
444  ZoneScope zone(Isolate::Current()->runtime_zone(), DELETE_ON_EXIT);
445 
446  InitializeVM();
447  v8::HandleScope handle_scope;
448  // Lines must be executed sequentially. Combining them into one script
449  // makes the bug go away.
450  const char* lines[] = {
451  "var x = [];",
452  "x[4] = 42;",
453  "var s = \"1073741828\";",
454  "x[s];",
455  "x[s] = 37;",
456  "x[4];",
457  "x[s];",
458  NULL
459  };
460 
461  Handle<Smi> fortytwo(Smi::FromInt(42));
462  Handle<Smi> thirtyseven(Smi::FromInt(37));
463  Handle<Object> results[] = {
464  FACTORY->undefined_value(),
465  fortytwo,
466  FACTORY->undefined_value(),
467  FACTORY->undefined_value(),
468  thirtyseven,
469  fortytwo,
470  thirtyseven // Bug yielded 42 here.
471  };
472 
473  const char* line;
474  for (int i = 0; (line = lines[i]); i++) {
475  printf("%s\n", line);
476  v8::Local<v8::Value> result =
477  v8::Script::Compile(v8::String::New(line))->Run();
478  CHECK_EQ(results[i]->IsUndefined(), result->IsUndefined());
479  CHECK_EQ(results[i]->IsNumber(), result->IsNumber());
480  if (result->IsNumber()) {
481  CHECK_EQ(Smi::cast(results[i]->ToSmi()->ToObjectChecked())->value(),
482  result->ToInt32()->Value());
483  }
484  }
485 }
486 
487 
488 TEST(SliceFromCons) {
489  FLAG_string_slices = true;
490  InitializeVM();
491  v8::HandleScope scope;
492  Handle<String> string =
493  FACTORY->NewStringFromAscii(CStrVector("parentparentparent"));
494  Handle<String> parent = FACTORY->NewConsString(string, string);
495  CHECK(parent->IsConsString());
496  CHECK(!parent->IsFlat());
497  Handle<String> slice = FACTORY->NewSubString(parent, 1, 25);
498  // After slicing, the original string becomes a flat cons.
499  CHECK(parent->IsFlat());
500  CHECK(slice->IsSlicedString());
502  ConsString::cast(*parent)->first());
503  CHECK(SlicedString::cast(*slice)->parent()->IsSeqString());
504  CHECK(slice->IsFlat());
505 }
506 
507 
509  public:
511  : data_(vector) {}
512  virtual ~AsciiVectorResource() {}
513  virtual size_t length() const { return data_.length(); }
514  virtual const char* data() const { return data_.start(); }
515  private:
516  i::Vector<const char> data_;
517 };
518 
519 
520 TEST(SliceFromExternal) {
521  FLAG_string_slices = true;
522  InitializeVM();
523  v8::HandleScope scope;
524  AsciiVectorResource resource(
525  i::Vector<const char>("abcdefghijklmnopqrstuvwxyz", 26));
526  Handle<String> string = FACTORY->NewExternalStringFromAscii(&resource);
527  CHECK(string->IsExternalString());
528  Handle<String> slice = FACTORY->NewSubString(string, 1, 25);
529  CHECK(slice->IsSlicedString());
530  CHECK(string->IsExternalString());
531  CHECK_EQ(SlicedString::cast(*slice)->parent(), *string);
532  CHECK(SlicedString::cast(*slice)->parent()->IsExternalString());
533  CHECK(slice->IsFlat());
534 }
535 
536 
537 TEST(TrivialSlice) {
538  // This tests whether a slice that contains the entire parent string
539  // actually creates a new string (it should not).
540  FLAG_string_slices = true;
541  InitializeVM();
542  HandleScope scope;
543  v8::Local<v8::Value> result;
544  Handle<String> string;
545  const char* init = "var str = 'abcdefghijklmnopqrstuvwxyz';";
546  const char* check = "str.slice(0,26)";
547  const char* crosscheck = "str.slice(1,25)";
548 
549  CompileRun(init);
550 
551  result = CompileRun(check);
552  CHECK(result->IsString());
553  string = v8::Utils::OpenHandle(v8::String::Cast(*result));
554  CHECK(!string->IsSlicedString());
555 
556  string = FACTORY->NewSubString(string, 0, 26);
557  CHECK(!string->IsSlicedString());
558  result = CompileRun(crosscheck);
559  CHECK(result->IsString());
560  string = v8::Utils::OpenHandle(v8::String::Cast(*result));
561  CHECK(string->IsSlicedString());
562  CHECK_EQ("bcdefghijklmnopqrstuvwxy", *(string->ToCString()));
563 }
564 
565 
566 TEST(SliceFromSlice) {
567  // This tests whether a slice that contains the entire parent string
568  // actually creates a new string (it should not).
569  FLAG_string_slices = true;
570  InitializeVM();
571  HandleScope scope;
572  v8::Local<v8::Value> result;
573  Handle<String> string;
574  const char* init = "var str = 'abcdefghijklmnopqrstuvwxyz';";
575  const char* slice = "var slice = str.slice(1,-1); slice";
576  const char* slice_from_slice = "slice.slice(1,-1);";
577 
578  CompileRun(init);
579  result = CompileRun(slice);
580  CHECK(result->IsString());
581  string = v8::Utils::OpenHandle(v8::String::Cast(*result));
582  CHECK(string->IsSlicedString());
583  CHECK(SlicedString::cast(*string)->parent()->IsSeqString());
584  CHECK_EQ("bcdefghijklmnopqrstuvwxy", *(string->ToCString()));
585 
586  result = CompileRun(slice_from_slice);
587  CHECK(result->IsString());
588  string = v8::Utils::OpenHandle(v8::String::Cast(*result));
589  CHECK(string->IsSlicedString());
590  CHECK(SlicedString::cast(*string)->parent()->IsSeqString());
591  CHECK_EQ("cdefghijklmnopqrstuvwx", *(string->ToCString()));
592 }
593 
594 
595 TEST(AsciiArrayJoin) {
596  // Set heap limits.
597  static const int K = 1024;
598  v8::ResourceConstraints constraints;
599  constraints.set_max_young_space_size(256 * K);
600  constraints.set_max_old_space_size(4 * K * K);
601  v8::SetResourceConstraints(&constraints);
602 
603  // String s is made of 2^17 = 131072 'c' characters and a is an array
604  // starting with 'bad', followed by 2^14 times the string s. That means the
605  // total length of the concatenated strings is 2^31 + 3. So on 32bit systems
606  // summing the lengths of the strings (as Smis) overflows and wraps.
607  static const char* join_causing_out_of_memory =
608  "var two_14 = Math.pow(2, 14);"
609  "var two_17 = Math.pow(2, 17);"
610  "var s = Array(two_17 + 1).join('c');"
611  "var a = ['bad'];"
612  "for (var i = 1; i <= two_14; i++) a.push(s);"
613  "a.join("");";
614 
615  v8::HandleScope scope;
616  LocalContext context;
618  v8::Local<v8::Script> script =
619  v8::Script::Compile(v8::String::New(join_causing_out_of_memory));
620  v8::Local<v8::Value> result = script->Run();
621 
622  // Check for out of memory state.
623  CHECK(result.IsEmpty());
624  CHECK(context->HasOutOfMemoryException());
625 }
626 
627 
628 static void CheckException(const char* source) {
629  // An empty handle is returned upon exception.
630  CHECK(CompileRun(source).IsEmpty());
631 }
632 
633 
634 TEST(RobustSubStringStub) {
635  // This tests whether the SubStringStub can handle unsafe arguments.
636  // If not recognized, those unsafe arguments lead to out-of-bounds reads.
637  FLAG_allow_natives_syntax = true;
638  InitializeVM();
639  HandleScope scope;
640  v8::Local<v8::Value> result;
641  Handle<String> string;
642  CompileRun("var short = 'abcdef';");
643 
644  // Invalid indices.
645  CheckException("%_SubString(short, 0, 10000);");
646  CheckException("%_SubString(short, -1234, 5);");
647  CheckException("%_SubString(short, 5, 2);");
648  // Special HeapNumbers.
649  CheckException("%_SubString(short, 1, Infinity);");
650  CheckException("%_SubString(short, NaN, 5);");
651  // String arguments.
652  CheckException("%_SubString(short, '2', '5');");
653  // Ordinary HeapNumbers can be handled (in runtime).
654  result = CompileRun("%_SubString(short, Math.sqrt(4), 5.1);");
655  string = v8::Utils::OpenHandle(v8::String::Cast(*result));
656  CHECK_EQ("cde", *(string->ToCString()));
657 
658  CompileRun("var long = 'abcdefghijklmnopqrstuvwxyz';");
659  // Invalid indices.
660  CheckException("%_SubString(long, 0, 10000);");
661  CheckException("%_SubString(long, -1234, 17);");
662  CheckException("%_SubString(long, 17, 2);");
663  // Special HeapNumbers.
664  CheckException("%_SubString(long, 1, Infinity);");
665  CheckException("%_SubString(long, NaN, 17);");
666  // String arguments.
667  CheckException("%_SubString(long, '2', '17');");
668  // Ordinary HeapNumbers within bounds can be handled (in runtime).
669  result = CompileRun("%_SubString(long, Math.sqrt(4), 17.1);");
670  string = v8::Utils::OpenHandle(v8::String::Cast(*result));
671  CHECK_EQ("cdefghijklmnopq", *(string->ToCString()));
672 
673  // Test that out-of-bounds substring of a slice fails when the indices
674  // would have been valid for the underlying string.
675  CompileRun("var slice = long.slice(1, 15);");
676  CheckException("%_SubString(slice, 0, 17);");
677 }
678 
679 
680 TEST(RegExpOverflow) {
681  // Result string has the length 2^32, causing a 32-bit integer overflow.
682  InitializeVM();
683  HandleScope scope;
684  LocalContext context;
686  v8::Local<v8::Value> result = CompileRun(
687  "var a = 'a'; "
688  "for (var i = 0; i < 16; i++) { "
689  " a += a; "
690  "} "
691  "a.replace(/a/g, a); ");
692  CHECK(result.IsEmpty());
693  CHECK(context->HasOutOfMemoryException());
694 }
695 
696 
697 TEST(StringReplaceAtomTwoByteResult) {
698  InitializeVM();
699  HandleScope scope;
700  LocalContext context;
701  v8::Local<v8::Value> result = CompileRun(
702  "var subject = 'ascii~only~string~'; "
703  "var replace = '\x80'; "
704  "subject.replace(/~/g, replace); ");
705  CHECK(result->IsString());
706  Handle<String> string = v8::Utils::OpenHandle(v8::String::Cast(*result));
707  CHECK(string->IsSeqTwoByteString());
708 
709  v8::Local<v8::String> expected = v8_str("ascii\x80only\x80string\x80");
710  CHECK(expected->Equals(result));
711 }
712 
713 
714 TEST(IsAscii) {
715  CHECK(String::IsAscii(static_cast<char*>(NULL), 0));
716  CHECK(String::IsAscii(static_cast<uc16*>(NULL), 0));
717 }
const SwVfpRegister s2
static Local< Script > Compile(Handle< String > source, ScriptOrigin *origin=NULL, ScriptData *pre_data=NULL, Handle< String > script_data=Handle< String >())
Definition: api.cc:1568
void FlattenString(Handle< String > string)
Definition: handles.cc:211
V8EXPORT int WriteUtf8(char *buffer, int length=-1, int *nchars_ref=NULL, int options=NO_OPTIONS) const
Definition: api.cc:3852
void set_max_young_space_size(int value)
Definition: v8.h:2638
#define CHECK_EQ(expected, value)
Definition: checks.h:219
bool HasOutOfMemoryException()
Definition: api.cc:4521
static Smi * FromInt(int value)
Definition: objects-inl.h:981
#define CHECK_GT(a, b)
Definition: checks.h:227
static V8EXPORT Local< String > New(const char *data, int length=-1)
Definition: api.cc:4779
V8EXPORT Local< Int32 > ToInt32() const
Definition: api.cc:2597
unsigned short uint16_t
Definition: unicode.cc:46
#define CHECK(condition)
Definition: checks.h:56
AsciiResource(Vector< const char > string)
Definition: test-strings.cc:70
virtual const char * data() const
static Smi * cast(Object *object)
unsigned int seed
Definition: test-strings.cc:18
static bool IsAscii(const char *chars, int length)
Definition: objects.h:7443
int foo
virtual size_t length() const
Definition: test-strings.cc:59
static const int kMinLength
Definition: objects.h:7666
void set_max_old_space_size(int value)
Definition: v8.h:2640
static SlicedString * cast(Object *obj)
V8EXPORT int Utf8Length() const
Definition: api.cc:3748
virtual ~AsciiVectorResource()
virtual size_t length() const
Definition: test-strings.cc:74
static String * Cast(v8::Value *obj)
Definition: v8.h:4417
virtual const uint16_t * data() const
Definition: test-strings.cc:58
Definition: v8.h:105
virtual const char * data() const
Definition: test-strings.cc:73
bool IsUndefined() const
Definition: v8.h:4472
T * NewArray(int length)
Definition: zone-inl.h:72
Vector< const char > CStrVector(const char *data)
Definition: utils.h:526
int StrLength(const char *string)
Definition: utils.h:234
bool IsString() const
Definition: v8.h:4508
const SwVfpRegister s1
V8EXPORT bool IsNumber() const
Definition: api.cc:2183
uint16_t uc16
Definition: globals.h:259
AsciiVectorResource(i::Vector< const char > vector)
static V8EXPORT Local< Integer > New(int32_t value)
Definition: api.cc:5228
virtual size_t length() const
bool IsEmpty() const
Definition: v8.h:209
Local< Value > Run()
Definition: api.cc:1598
#define FACTORY
Definition: isolate.h:1434
void Reset(Input input)
Definition: unicode-inl.h:233
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
Definition: flags.cc:301
static Persistent< Context > New(ExtensionConfiguration *extensions=NULL, Handle< ObjectTemplate > global_template=Handle< ObjectTemplate >(), Handle< Value > global_object=Handle< Value >())
Definition: api.cc:4411
static V8EXPORT Local< String > NewExternal(ExternalStringResource *resource)
Definition: api.cc:4871
bool V8EXPORT SetResourceConstraints(ResourceConstraints *constraints)
Definition: api.cc:596
static ConsString * cast(Object *obj)
void check(i::Vector< const char > string)
Definition: v8.h:106
Resource(Vector< const uc16 > string)
Definition: test-strings.cc:55
static V8EXPORT Local< Object > New()
Definition: api.cc:4957
V8EXPORT bool Set(Handle< Value > key, Handle< Value > value, PropertyAttribute attribs=None)
Definition: api.cc:2765
static void IgnoreOutOfMemoryException()
Definition: api.cc:5268