Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(276)

Side by Side Diff: src/wasm/wasm-js.cc

Issue 2636173002: [wasm] Enforce memory and table limits during instantiation. (Closed)
Patch Set: [wasm] Enforce memory and table limits during instantiation. Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/wasm/module-decoder.cc ('k') | src/wasm/wasm-limits.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/api-natives.h" 5 #include "src/api-natives.h"
6 #include "src/api.h" 6 #include "src/api.h"
7 #include "src/asmjs/asm-js.h" 7 #include "src/asmjs/asm-js.h"
8 #include "src/asmjs/asm-typer.h" 8 #include "src/asmjs/asm-typer.h"
9 #include "src/asmjs/asm-wasm-builder.h" 9 #include "src/asmjs/asm-wasm-builder.h"
10 #include "src/assert-scope.h" 10 #include "src/assert-scope.h"
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 DCHECK(thrower.error()); 347 DCHECK(thrower.error());
348 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); 348 resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
349 } else { 349 } else {
350 DCHECK(!thrower.error()); 350 DCHECK(!thrower.error());
351 resolver->Resolve(context, instance.ToLocalChecked()); 351 resolver->Resolve(context, instance.ToLocalChecked());
352 } 352 }
353 } 353 }
354 354
355 bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower, 355 bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower,
356 Local<Context> context, Local<v8::Object> object, 356 Local<Context> context, Local<v8::Object> object,
357 Local<String> property, int* result, int lower_bound, 357 Local<String> property, int* result,
358 int upper_bound) { 358 int64_t lower_bound, uint64_t upper_bound) {
359 v8::MaybeLocal<v8::Value> maybe = object->Get(context, property); 359 v8::MaybeLocal<v8::Value> maybe = object->Get(context, property);
360 v8::Local<v8::Value> value; 360 v8::Local<v8::Value> value;
361 if (maybe.ToLocal(&value)) { 361 if (maybe.ToLocal(&value)) {
362 int64_t number; 362 int64_t number;
363 if (!value->IntegerValue(context).To(&number)) return false; 363 if (!value->IntegerValue(context).To(&number)) return false;
364 if (number < static_cast<int64_t>(lower_bound)) { 364 if (number < lower_bound) {
365 thrower->RangeError("Property value %" PRId64 365 thrower->RangeError("Property value %" PRId64
366 " is below the lower bound %d", 366 " is below the lower bound %" PRIx64,
367 number, lower_bound); 367 number, lower_bound);
368 return false; 368 return false;
369 } 369 }
370 if (number > static_cast<int64_t>(upper_bound)) { 370 if (number > static_cast<int64_t>(upper_bound)) {
371 thrower->RangeError("Property value %" PRId64 371 thrower->RangeError("Property value %" PRId64
372 " is above the upper bound %d", 372 " is above the upper bound %" PRIu64,
373 number, upper_bound); 373 number, upper_bound);
374 return false; 374 return false;
375 } 375 }
376 *result = static_cast<int>(number); 376 *result = static_cast<int>(number);
377 return true; 377 return true;
378 } 378 }
379 return false; 379 return false;
380 } 380 }
381 381
382 const int max_table_size = 1 << 26;
383
384 void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) { 382 void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) {
385 v8::Isolate* isolate = args.GetIsolate(); 383 v8::Isolate* isolate = args.GetIsolate();
386 HandleScope scope(isolate); 384 HandleScope scope(isolate);
387 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), 385 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate),
388 "WebAssembly.Module()"); 386 "WebAssembly.Module()");
389 if (args.Length() < 1 || !args[0]->IsObject()) { 387 if (args.Length() < 1 || !args[0]->IsObject()) {
390 thrower.TypeError("Argument 0 must be a table descriptor"); 388 thrower.TypeError("Argument 0 must be a table descriptor");
391 return; 389 return;
392 } 390 }
393 Local<Context> context = isolate->GetCurrentContext(); 391 Local<Context> context = isolate->GetCurrentContext();
394 Local<v8::Object> descriptor = args[0]->ToObject(context).ToLocalChecked(); 392 Local<v8::Object> descriptor = args[0]->ToObject(context).ToLocalChecked();
395 // The descriptor's 'element'. 393 // The descriptor's 'element'.
396 { 394 {
397 v8::MaybeLocal<v8::Value> maybe = 395 v8::MaybeLocal<v8::Value> maybe =
398 descriptor->Get(context, v8_str(isolate, "element")); 396 descriptor->Get(context, v8_str(isolate, "element"));
399 v8::Local<v8::Value> value; 397 v8::Local<v8::Value> value;
400 if (!maybe.ToLocal(&value)) return; 398 if (!maybe.ToLocal(&value)) return;
401 v8::Local<v8::String> string; 399 v8::Local<v8::String> string;
402 if (!value->ToString(context).ToLocal(&string)) return; 400 if (!value->ToString(context).ToLocal(&string)) return;
403 bool equal; 401 bool equal;
404 if (!string->Equals(context, v8_str(isolate, "anyfunc")).To(&equal)) return; 402 if (!string->Equals(context, v8_str(isolate, "anyfunc")).To(&equal)) return;
405 if (!equal) { 403 if (!equal) {
406 thrower.TypeError("Descriptor property 'element' must be 'anyfunc'"); 404 thrower.TypeError("Descriptor property 'element' must be 'anyfunc'");
407 return; 405 return;
408 } 406 }
409 } 407 }
410 // The descriptor's 'initial'. 408 // The descriptor's 'initial'.
411 int initial; 409 int initial = 0;
412 if (!GetIntegerProperty(isolate, &thrower, context, descriptor, 410 if (!GetIntegerProperty(isolate, &thrower, context, descriptor,
413 v8_str(isolate, "initial"), &initial, 0, 411 v8_str(isolate, "initial"), &initial, 0,
414 max_table_size)) { 412 i::wasm::kV8MaxWasmTableSize)) {
415 return; 413 return;
416 } 414 }
417 // The descriptor's 'maximum'. 415 // The descriptor's 'maximum'.
418 int maximum = 0; 416 int maximum = -1;
419 Local<String> maximum_key = v8_str(isolate, "maximum"); 417 Local<String> maximum_key = v8_str(isolate, "maximum");
420 Maybe<bool> has_maximum = descriptor->Has(context, maximum_key); 418 Maybe<bool> has_maximum = descriptor->Has(context, maximum_key);
421 419
422 if (has_maximum.IsNothing()) { 420 if (!has_maximum.IsNothing() && has_maximum.FromJust()) {
423 // There has been an exception, just return.
424 return;
425 }
426 if (has_maximum.FromJust()) {
427 if (!GetIntegerProperty(isolate, &thrower, context, descriptor, maximum_key, 421 if (!GetIntegerProperty(isolate, &thrower, context, descriptor, maximum_key,
428 &maximum, initial, max_table_size)) { 422 &maximum, initial,
423 i::wasm::kSpecMaxWasmTableSize)) {
429 return; 424 return;
430 } 425 }
431 } else {
432 maximum = static_cast<int>(i::wasm::kV8MaxWasmTableSize);
433 } 426 }
434 427
435 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 428 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
436 i::Handle<i::FixedArray> fixed_array; 429 i::Handle<i::FixedArray> fixed_array;
437 i::Handle<i::JSObject> table_obj = 430 i::Handle<i::JSObject> table_obj =
438 i::WasmTableObject::New(i_isolate, initial, maximum, &fixed_array); 431 i::WasmTableObject::New(i_isolate, initial, maximum, &fixed_array);
439 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); 432 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
440 return_value.Set(Utils::ToLocal(table_obj)); 433 return_value.Set(Utils::ToLocal(table_obj));
441 } 434 }
442 435
443 void WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) { 436 void WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) {
444 v8::Isolate* isolate = args.GetIsolate(); 437 v8::Isolate* isolate = args.GetIsolate();
445 HandleScope scope(isolate); 438 HandleScope scope(isolate);
446 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), 439 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate),
447 "WebAssembly.Memory()"); 440 "WebAssembly.Memory()");
448 if (args.Length() < 1 || !args[0]->IsObject()) { 441 if (args.Length() < 1 || !args[0]->IsObject()) {
449 thrower.TypeError("Argument 0 must be a memory descriptor"); 442 thrower.TypeError("Argument 0 must be a memory descriptor");
450 return; 443 return;
451 } 444 }
452 Local<Context> context = isolate->GetCurrentContext(); 445 Local<Context> context = isolate->GetCurrentContext();
453 Local<v8::Object> descriptor = args[0]->ToObject(context).ToLocalChecked(); 446 Local<v8::Object> descriptor = args[0]->ToObject(context).ToLocalChecked();
454 // The descriptor's 'initial'. 447 // The descriptor's 'initial'.
455 int initial; 448 int initial = 0;
456 if (!GetIntegerProperty(isolate, &thrower, context, descriptor, 449 if (!GetIntegerProperty(isolate, &thrower, context, descriptor,
457 v8_str(isolate, "initial"), &initial, 0, 65536)) { 450 v8_str(isolate, "initial"), &initial, 0,
451 i::wasm::kV8MaxWasmMemoryPages)) {
458 return; 452 return;
459 } 453 }
460 // The descriptor's 'maximum'. 454 // The descriptor's 'maximum'.
461 int maximum = 0; 455 int maximum = -1;
462 Local<String> maximum_key = v8_str(isolate, "maximum"); 456 Local<String> maximum_key = v8_str(isolate, "maximum");
463 Maybe<bool> has_maximum = descriptor->Has(context, maximum_key); 457 Maybe<bool> has_maximum = descriptor->Has(context, maximum_key);
464 458
465 if (has_maximum.IsNothing()) { 459 if (!has_maximum.IsNothing() && has_maximum.FromJust()) {
466 // There has been an exception, just return.
467 return;
468 }
469 if (has_maximum.FromJust()) {
470 if (!GetIntegerProperty(isolate, &thrower, context, descriptor, maximum_key, 460 if (!GetIntegerProperty(isolate, &thrower, context, descriptor, maximum_key,
471 &maximum, initial, 65536)) { 461 &maximum, initial,
462 i::wasm::kSpecMaxWasmMemoryPages)) {
472 return; 463 return;
473 } 464 }
474 } 465 }
475 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 466 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
476 size_t size = static_cast<size_t>(i::wasm::WasmModule::kPageSize) * 467 size_t size = static_cast<size_t>(i::wasm::WasmModule::kPageSize) *
477 static_cast<size_t>(initial); 468 static_cast<size_t>(initial);
478 i::Handle<i::JSArrayBuffer> buffer = 469 i::Handle<i::JSArrayBuffer> buffer =
479 i::wasm::NewArrayBuffer(i_isolate, size, i::FLAG_wasm_guard_pages); 470 i::wasm::NewArrayBuffer(i_isolate, size, i::FLAG_wasm_guard_pages);
480 if (buffer.is_null()) { 471 if (buffer.is_null()) {
481 thrower.RangeError("could not allocate memory"); 472 thrower.RangeError("could not allocate memory");
482 return; 473 return;
483 } 474 }
484 i::Handle<i::JSObject> memory_obj = i::WasmMemoryObject::New( 475 i::Handle<i::JSObject> memory_obj =
485 i_isolate, buffer, has_maximum.FromJust() ? maximum : -1); 476 i::WasmMemoryObject::New(i_isolate, buffer, maximum);
486 args.GetReturnValue().Set(Utils::ToLocal(memory_obj)); 477 args.GetReturnValue().Set(Utils::ToLocal(memory_obj));
487 } 478 }
488 479
489 void WebAssemblyTableGetLength( 480 void WebAssemblyTableGetLength(
490 const v8::FunctionCallbackInfo<v8::Value>& args) { 481 const v8::FunctionCallbackInfo<v8::Value>& args) {
491 v8::Isolate* isolate = args.GetIsolate(); 482 v8::Isolate* isolate = args.GetIsolate();
492 Local<Context> context = isolate->GetCurrentContext(); 483 Local<Context> context = isolate->GetCurrentContext();
493 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); 484 i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
494 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), 485 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()),
495 i::Handle<i::Symbol>(i_context->wasm_table_sym()), 486 i::Handle<i::Symbol>(i_context->wasm_table_sym()),
(...skipping 20 matching lines...) Expand all
516 auto receiver = 507 auto receiver =
517 i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This())); 508 i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This()));
518 i::Handle<i::FixedArray> old_array(receiver->functions(), i_isolate); 509 i::Handle<i::FixedArray> old_array(receiver->functions(), i_isolate);
519 int old_size = old_array->length(); 510 int old_size = old_array->length();
520 int64_t new_size64 = 0; 511 int64_t new_size64 = 0;
521 if (args.Length() > 0 && !args[0]->IntegerValue(context).To(&new_size64)) { 512 if (args.Length() > 0 && !args[0]->IntegerValue(context).To(&new_size64)) {
522 return; 513 return;
523 } 514 }
524 new_size64 += old_size; 515 new_size64 += old_size;
525 516
526 if (new_size64 < old_size || new_size64 > receiver->maximum_length()) { 517 int64_t max_size64 = receiver->maximum_length();
518 if (max_size64 < 0 ||
519 max_size64 > static_cast<int64_t>(i::wasm::kV8MaxWasmTableSize)) {
520 max_size64 = i::wasm::kV8MaxWasmTableSize;
521 }
522
523 if (new_size64 < old_size || new_size64 > max_size64) {
527 v8::Local<v8::Value> e = v8::Exception::RangeError( 524 v8::Local<v8::Value> e = v8::Exception::RangeError(
528 v8_str(isolate, new_size64 < old_size ? "trying to shrink table" 525 v8_str(isolate, new_size64 < old_size ? "trying to shrink table"
529 : "maximum table size exceeded")); 526 : "maximum table size exceeded"));
530 isolate->ThrowException(e); 527 isolate->ThrowException(e);
531 return; 528 return;
532 } 529 }
533 530
534 int new_size = static_cast<int>(new_size64); 531 int new_size = static_cast<int>(new_size64);
535 i::WasmTableObject::Grow(i_isolate, receiver, 532 i::WasmTableObject::Grow(i_isolate, receiver,
536 static_cast<uint32_t>(new_size - old_size)); 533 static_cast<uint32_t>(new_size - old_size));
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
887 i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate); 884 i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate);
888 return HasBrand(value, symbol); 885 return HasBrand(value, symbol);
889 } 886 }
890 887
891 bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) { 888 bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) {
892 i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate); 889 i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate);
893 return HasBrand(value, symbol); 890 return HasBrand(value, symbol);
894 } 891 }
895 } // namespace internal 892 } // namespace internal
896 } // namespace v8 893 } // namespace v8
OLDNEW
« no previous file with comments | « src/wasm/module-decoder.cc ('k') | src/wasm/wasm-limits.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698