1 /* 2 * Copyright (C) 2020-2021 Jo-Philipp Wich <jo@mein.io> 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include <stdarg.h> 18 #include <string.h> 19 #include <assert.h> 20 #include <ctype.h> 21 #include <math.h> 22 #include <errno.h> 23 #include <limits.h> 24 #include <fcntl.h> 25 #include <unistd.h> 26 27 #include "ucode/vm.h" 28 #include "ucode/compiler.h" 29 #include "ucode/program.h" 30 #include "ucode/lib.h" /* uc_error_context_format() */ 31 #include "ucode/platform.h" 32 33 #undef __insn 34 #define __insn(_name) #_name, 35 36 static const char *insn_names[__I_MAX] = { 37 __insns 38 }; 39 40 static const int8_t insn_operand_bytes[__I_MAX] = { 41 [I_LOAD] = 4, 42 [I_LOAD8] = 1, 43 [I_LOAD16] = 2, 44 [I_LOAD32] = 4, 45 46 [I_LREXP] = 4, 47 48 [I_LLOC] = 4, 49 [I_LVAR] = 4, 50 [I_LUPV] = 4, 51 52 [I_CLFN] = 4, 53 [I_ARFN] = 4, 54 55 [I_SLOC] = 4, 56 [I_SUPV] = 4, 57 [I_SVAR] = 4, 58 59 [I_ULOC] = 4, 60 [I_UUPV] = 4, 61 [I_UVAR] = 4, 62 [I_UVAL] = 1, 63 64 [I_NARR] = 4, 65 [I_PARR] = 4, 66 67 [I_NOBJ] = 4, 68 [I_SOBJ] = 4, 69 70 [I_JMP] = -4, 71 [I_JMPZ] = -4, 72 [I_JMPNT] = 4, 73 74 [I_COPY] = 1, 75 76 [I_CALL] = 4, 77 78 [I_IMPORT] = 4, 79 [I_EXPORT] = 4, 80 [I_DYNLOAD] = 4 81 }; 82 83 static const char *exception_type_strings[] = { 84 [EXCEPTION_SYNTAX] = "Syntax error", 85 [EXCEPTION_RUNTIME] = "Runtime error", 86 [EXCEPTION_TYPE] = "Type error", 87 [EXCEPTION_REFERENCE] = "Reference error", 88 [EXCEPTION_USER] = "Error", 89 [EXCEPTION_EXIT] = "Exit" 90 }; 91 92 93 static const char * 94 uc_vm_insn_to_name(uc_vm_insn_t insn) 95 { 96 if (insn < 0 || insn >= __I_MAX) 97 return "(unknown)"; 98 99 return insn_names[insn]; 100 } 101 102 static int8_t 103 uc_vm_insn_to_argtype(uc_vm_insn_t insn) 104 { 105 if (insn < 0 || insn >= __I_MAX) 106 return 0; 107 108 return insn_operand_bytes[insn]; 109 } 110 111 static void 112 uc_vm_reset_stack(uc_vm_t *vm) 113 { 114 while (vm->stack.count > 0) { 115 vm->stack.count--; 116 ucv_put(vm->stack.entries[vm->stack.count]); 117 vm->stack.entries[vm->stack.count] = NULL; 118 } 119 } 120 121 static uc_value_t * 122 uc_vm_callframe_pop(uc_vm_t *vm); 123 124 static void 125 uc_vm_reset_callframes(uc_vm_t *vm) 126 { 127 while (vm->callframes.count > 0) 128 ucv_put(uc_vm_callframe_pop(vm)); 129 } 130 131 static uc_value_t * 132 uc_vm_alloc_global_scope(uc_vm_t *vm) 133 { 134 uc_value_t *scope, *arr; 135 size_t i; 136 137 scope = ucv_object_new(vm); 138 139 /* build default require() search path */ 140 arr = ucv_array_new(vm); 141 142 for (i = 0; i < vm->config->module_search_path.count; i++) 143 ucv_array_push(arr, ucv_string_new(vm->config->module_search_path.entries[i])); 144 145 /* register module related constants */ 146 ucv_object_add(scope, "REQUIRE_SEARCH_PATH", arr); 147 ucv_object_add(scope, "modules", ucv_object_new(vm)); 148 149 /* register scope math constants */ 150 ucv_object_add(scope, "NaN", ucv_double_new(NAN)); 151 ucv_object_add(scope, "Infinity", ucv_double_new(INFINITY)); 152 153 /* register global property */ 154 ucv_object_add(scope, "global", ucv_get(scope)); 155 156 uc_vm_scope_set(vm, scope); 157 158 return scope; 159 } 160 161 static void 162 uc_vm_output_exception(uc_vm_t *vm, uc_exception_t *ex); 163 164 static void 165 uc_vm_signal_handler(int sig) 166 { 167 uc_vm_t *vm = uc_thread_context_get()->signal_handler_vm; 168 169 assert(vm); 170 171 uc_vm_signal_raise(vm, sig); 172 } 173 174 static void 175 uc_vm_signal_handlers_setup(uc_vm_t *vm) 176 { 177 uc_thread_context_t *tctx; 178 179 memset(&vm->signal, 0, sizeof(vm->signal)); 180 181 vm->signal.sigpipe[0] = -1; 182 vm->signal.sigpipe[1] = -1; 183 184 if (!vm->config->setup_signal_handlers) 185 return; 186 187 tctx = uc_thread_context_get(); 188 189 if (tctx->signal_handler_vm) 190 return; 191 192 if (pipe2(vm->signal.sigpipe, O_CLOEXEC | O_NONBLOCK) != 0) 193 return; 194 195 vm->signal.handler = ucv_array_new_length(vm, UC_SYSTEM_SIGNAL_COUNT); 196 197 vm->signal.sa.sa_handler = uc_vm_signal_handler; 198 vm->signal.sa.sa_flags = SA_RESTART | SA_ONSTACK; 199 sigemptyset(&vm->signal.sa.sa_mask); 200 201 tctx->signal_handler_vm = vm; 202 } 203 204 static void 205 uc_vm_signal_handlers_reset(uc_vm_t *vm) 206 { 207 uc_thread_context_t *tctx = uc_thread_context_get(); 208 struct sigaction sa = { 0 }; 209 size_t i, signo; 210 211 if (vm != tctx->signal_handler_vm) 212 return; 213 214 sa.sa_handler = SIG_DFL; 215 sigemptyset(&sa.sa_mask); 216 217 for (signo = 0; signo < ucv_array_length(vm->signal.handler); signo++) 218 if (ucv_is_callable(ucv_array_get(vm->signal.handler, signo))) 219 sigaction(signo, &sa, NULL); 220 221 for (i = 0; i < ARRAY_SIZE(vm->signal.sigpipe); i++) { 222 if (vm->signal.sigpipe[i] > STDERR_FILENO) 223 close(vm->signal.sigpipe[i]); 224 225 vm->signal.sigpipe[i] = -1; 226 } 227 228 tctx->signal_handler_vm = NULL; 229 } 230 231 void uc_vm_init(uc_vm_t *vm, uc_parse_config_t *config) 232 { 233 vm->exception.type = EXCEPTION_NONE; 234 vm->exception.message = NULL; 235 236 vm->config = config ? config : &uc_default_parse_config; 237 238 vm->open_upvals = NULL; 239 240 vm->values.prev = &vm->values; 241 vm->values.next = &vm->values; 242 243 vm->strbuf = NULL; 244 245 vm->output = stdout; 246 247 uc_vm_reset_stack(vm); 248 249 uc_vm_alloc_global_scope(vm); 250 251 uc_vm_exception_handler_set(vm, uc_vm_output_exception); 252 253 uc_vm_trace_set(vm, 0); 254 255 uc_vm_signal_handlers_setup(vm); 256 257 uc_thread_context_get()->refcount++; 258 } 259 260 void uc_vm_free(uc_vm_t *vm) 261 { 262 uc_thread_context_t *ctx; 263 uc_upvalref_t *ref; 264 size_t i; 265 266 uc_vm_signal_handlers_reset(vm); 267 268 ucv_put(vm->exception.stacktrace); 269 free(vm->exception.message); 270 271 while (vm->open_upvals) { 272 ref = vm->open_upvals->next; 273 ucv_put(&vm->open_upvals->header); 274 vm->open_upvals = ref; 275 } 276 277 for (i = 0; i < vm->restypes.count; i++) 278 ucv_put(vm->restypes.entries[i]->proto); 279 280 uc_vm_reset_callframes(vm); 281 uc_vm_reset_stack(vm); 282 uc_vector_clear(&vm->stack); 283 uc_vector_clear(&vm->callframes); 284 285 printbuf_free(vm->strbuf); 286 287 ucv_freeall(vm); 288 289 for (i = 0; i < vm->restypes.count; i++) 290 free(vm->restypes.entries[i]); 291 292 uc_vector_clear(&vm->restypes); 293 294 ctx = uc_thread_context_get(); 295 296 assert(ctx->refcount > 0); 297 298 if (--ctx->refcount == 0) 299 uc_thread_context_free(); 300 } 301 302 static uc_chunk_t * 303 uc_vm_frame_chunk(uc_callframe_t *frame) 304 { 305 return frame->closure ? &frame->closure->function->chunk : NULL; 306 } 307 308 static uc_program_t * 309 uc_vm_frame_program(uc_callframe_t *frame) 310 { 311 return frame->closure ? frame->closure->function->program : NULL; 312 } 313 314 static uc_source_t * 315 uc_vm_frame_source(uc_callframe_t *frame) 316 { 317 return frame->closure ? uc_program_function_source(frame->closure->function) : NULL; 318 } 319 320 static uc_callframe_t * 321 uc_vm_current_frame(uc_vm_t *vm) 322 { 323 return uc_vector_last(&vm->callframes); 324 } 325 326 static uc_program_t * 327 uc_vm_current_program(uc_vm_t *vm) 328 { 329 return uc_vm_frame_program(uc_vm_current_frame(vm)); 330 } 331 332 static bool 333 uc_vm_is_strict(uc_vm_t *vm) 334 { 335 return uc_vm_current_frame(vm)->strict; 336 } 337 338 static uc_vm_insn_t 339 uc_vm_decode_insn(uc_vm_t *vm, uc_callframe_t *frame, uc_chunk_t *chunk) 340 { 341 uc_vm_insn_t insn; 342 int8_t argtype; 343 344 #ifndef NDEBUG 345 uint8_t *end = chunk->entries + chunk->count; 346 #endif 347 348 assert(frame->ip < end); 349 350 insn = frame->ip[0]; 351 frame->ip++; 352 353 argtype = uc_vm_insn_to_argtype(insn); 354 355 assert(frame->ip + abs(argtype) <= end); 356 357 switch (argtype) { 358 case 0: 359 break; 360 361 case -4: 362 vm->arg.s32 = ( 363 frame->ip[0] * 0x1000000UL + 364 frame->ip[1] * 0x10000UL + 365 frame->ip[2] * 0x100UL + 366 frame->ip[3] 367 ) - 0x7fffffff; 368 frame->ip += 4; 369 break; 370 371 case 1: 372 vm->arg.u8 = frame->ip[0]; 373 frame->ip++; 374 break; 375 376 case 2: 377 vm->arg.u16 = ( 378 frame->ip[0] * 0x100 + 379 frame->ip[1] 380 ); 381 frame->ip += 2; 382 break; 383 384 case 4: 385 vm->arg.u32 = ( 386 frame->ip[0] * 0x1000000UL + 387 frame->ip[1] * 0x10000UL + 388 frame->ip[2] * 0x100UL + 389 frame->ip[3] 390 ); 391 frame->ip += 4; 392 break; 393 394 default: 395 fprintf(stderr, "Unhandled operand format: %" PRId8 "\n", argtype); 396 abort(); 397 } 398 399 return insn; 400 } 401 402 403 static char * 404 uc_vm_format_val(uc_vm_t *vm, uc_value_t *val) 405 { 406 if (!vm->strbuf) 407 vm->strbuf = xprintbuf_new(); 408 else 409 printbuf_reset(vm->strbuf); 410 411 ucv_to_stringbuf(NULL, vm->strbuf, val, true); 412 413 if (printbuf_length(vm->strbuf) >= 64) { 414 printbuf_memset(vm->strbuf, 60, '.', 3); 415 printbuf_memset(vm->strbuf, 63, 0, 1); 416 } 417 418 return vm->strbuf->buf; 419 } 420 421 static void 422 uc_vm_frame_dump(uc_vm_t *vm, uc_callframe_t *frame) 423 { 424 uc_chunk_t *chunk = uc_vm_frame_chunk(frame); 425 uc_function_t *function; 426 uc_closure_t *closure; 427 uc_upvalref_t *ref; 428 uc_value_t *v; 429 size_t i; 430 431 fprintf(stderr, " [*] CALLFRAME[%zx]\n", 432 frame - vm->callframes.entries); 433 434 fprintf(stderr, " |- stackframe %zu/%zu\n", 435 frame->stackframe, vm->stack.count); 436 437 fprintf(stderr, " |- ctx %s\n", 438 uc_vm_format_val(vm, frame->ctx)); 439 440 if (chunk) { 441 closure = frame->closure; 442 function = closure->function; 443 444 fprintf(stderr, " `- %zu upvalues\n", 445 function->nupvals); 446 447 for (i = 0; i < function->nupvals; i++) { 448 ref = closure->upvals[i]; 449 v = uc_chunk_debug_get_variable(chunk, 0, i, true); 450 451 fprintf(stderr, " [%zu] <%p> %s ", 452 i, (void *)ref, uc_vm_format_val(vm, v)); 453 454 if (!ref) { 455 fprintf(stderr, "{unresolved}\n"); 456 } 457 else if (ref->closed) { 458 fprintf(stderr, "{closed} %s\n", 459 uc_vm_format_val(vm, ref->value)); 460 } 461 else { 462 fprintf(stderr, "{open[%zu]} %s\n", 463 ref->slot, 464 uc_vm_format_val(vm, vm->stack.entries[ref->slot])); 465 } 466 467 ucv_put(v); 468 } 469 } 470 } 471 472 static uc_value_t * 473 uc_vm_resolve_upval(uc_vm_t *vm, uc_value_t *value) 474 { 475 uc_upvalref_t *ref; 476 477 #ifdef __clang_analyzer__ 478 /* Clang static analyzer does not understand that ucv_type(NULL) can't 479 * possibly yield UC_UPVALUE. Nudge it. */ 480 if (value != NULL && ucv_type(value) == UC_UPVALUE) 481 #else 482 if (ucv_type(value) == UC_UPVALUE) 483 #endif 484 { 485 ref = (uc_upvalref_t *)value; 486 487 if (ref->closed) 488 return ucv_get(ref->value); 489 else 490 return ucv_get(vm->stack.entries[ref->slot]); 491 } 492 493 return value; 494 } 495 496 void 497 uc_vm_stack_push(uc_vm_t *vm, uc_value_t *value) 498 { 499 uc_vector_push(&vm->stack, uc_vm_resolve_upval(vm, value)); 500 501 if (vm->trace) { 502 fprintf(stderr, " [+%zd] %s\n", 503 vm->stack.count - 1, 504 uc_vm_format_val(vm, vm->stack.entries[vm->stack.count - 1])); 505 } 506 } 507 508 uc_value_t * 509 uc_vm_stack_pop(uc_vm_t *vm) 510 { 511 uc_value_t *rv; 512 513 vm->stack.count--; 514 rv = vm->stack.entries[vm->stack.count]; 515 vm->stack.entries[vm->stack.count] = NULL; 516 517 if (vm->trace) { 518 fprintf(stderr, " [-%zd] %s\n", 519 vm->stack.count, 520 uc_vm_format_val(vm, rv)); 521 } 522 523 return rv; 524 } 525 526 uc_value_t * 527 uc_vm_stack_peek(uc_vm_t *vm, size_t offset) 528 { 529 return vm->stack.entries[vm->stack.count + (-1 - offset)]; 530 } 531 532 static void 533 uc_vm_stack_set(uc_vm_t *vm, size_t offset, uc_value_t *value) 534 { 535 if (vm->trace) { 536 fprintf(stderr, " [!%zu] %s\n", 537 offset, 538 uc_vm_format_val(vm, value)); 539 } 540 541 ucv_put(vm->stack.entries[offset]); 542 vm->stack.entries[offset] = value; 543 } 544 545 static void 546 uc_vm_call_native(uc_vm_t *vm, uc_value_t *ctx, uc_cfunction_t *fptr, bool mcall, size_t nargs) 547 { 548 uc_value_t *res = NULL; 549 uc_callframe_t *frame; 550 551 /* add new callframe */ 552 frame = uc_vector_push(&vm->callframes, { 553 .stackframe = vm->stack.count - nargs - 1, 554 .cfunction = fptr, 555 .closure = NULL, 556 .ctx = ctx, 557 .mcall = mcall 558 }); 559 560 if (vm->trace) 561 uc_vm_frame_dump(vm, frame); 562 563 res = fptr->cfn(vm, nargs); 564 565 /* Reset stack, check for callframe depth since an uncatched exception in managed 566 * code executed by fptr->cfn() could've reset the callframe stack already. */ 567 if (vm->callframes.count > 0) 568 ucv_put(uc_vm_callframe_pop(vm)); 569 570 /* push return value */ 571 if (!vm->exception.type) 572 uc_vm_stack_push(vm, res); 573 else 574 ucv_put(res); 575 } 576 577 static bool 578 uc_vm_call_function(uc_vm_t *vm, uc_value_t *ctx, uc_value_t *fno, bool mcall, size_t argspec) 579 { 580 size_t i, j, stackoff, nargs = argspec & 0xffff; 581 size_t nspreads = (argspec >> 16) & 0x7fff; 582 uc_callframe_t *frame = NULL; 583 uc_value_t *ellip, *arg; 584 uc_function_t *function; 585 uc_closure_t *closure; 586 uint16_t slot, tmp; 587 char *s; 588 589 /* XXX: make dependent on stack size */ 590 if (vm->callframes.count >= 1000) { 591 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, "Too much recursion"); 592 ucv_put(ctx); 593 ucv_put(fno); 594 595 return false; 596 } 597 598 stackoff = vm->stack.count - nargs - 1; 599 600 /* argument list contains spread operations, we need to reshuffle the stack */ 601 if (nspreads > 0) { 602 frame = uc_vm_current_frame(vm); 603 604 /* create temporary array */ 605 ellip = ucv_array_new_length(vm, nargs); 606 607 /* pop original stack values and push to temp array in reverse order */ 608 for (i = 0; i < nargs; i++) 609 ucv_array_push(ellip, uc_vm_stack_pop(vm)); 610 611 /* for each spread value index ... */ 612 for (i = 0, slot = nargs; i < nspreads; i++) { 613 /* decode stack depth value */ 614 tmp = frame->ip[0] * 0x100 + frame->ip[1]; 615 frame->ip += 2; 616 617 /* push each preceeding non-spread value to the stack */ 618 for (j = slot; j > tmp + 1UL; j--) 619 uc_vm_stack_push(vm, ucv_get(ucv_array_get(ellip, j - 1))); 620 621 /* read spread value at index... */ 622 slot = tmp; 623 arg = ucv_get(ucv_array_get(ellip, slot)); 624 625 /* ... ensure that it is an array type ... */ 626 if (ucv_type(arg) != UC_ARRAY) { 627 s = ucv_to_string(vm, arg); 628 uc_vm_raise_exception(vm, EXCEPTION_TYPE, "(%s) is not iterable", s); 629 free(s); 630 ucv_put(ctx); 631 ucv_put(fno); 632 ucv_put(ellip); 633 634 return false; 635 } 636 637 /* ... and push each spread array value as argument to the stack */ 638 for (j = 0; j < ucv_array_length(arg); j++) 639 uc_vm_stack_push(vm, ucv_get(ucv_array_get(arg, j))); 640 641 ucv_put(arg); 642 } 643 644 /* push remaining non-spread arguments to the stack */ 645 for (i = slot; i > 0; i--) 646 uc_vm_stack_push(vm, ucv_get(ucv_array_get(ellip, i - 1))); 647 648 /* free temp array */ 649 ucv_put(ellip); 650 651 /* update arg count */ 652 nargs = vm->stack.count - stackoff - 1; 653 } 654 655 /* is a native function */ 656 if (ucv_type(fno) == UC_CFUNCTION) { 657 uc_vm_call_native(vm, ctx, (uc_cfunction_t *)fno, mcall, nargs); 658 659 return true; 660 } 661 662 if (ucv_type(fno) != UC_CLOSURE) { 663 uc_vm_raise_exception(vm, EXCEPTION_TYPE, "left-hand side is not a function"); 664 ucv_put(ctx); 665 ucv_put(fno); 666 667 return false; 668 } 669 670 closure = (uc_closure_t *)fno; 671 function = closure->function; 672 673 /* fewer arguments on stack than function expects => pad */ 674 if (nargs < function->nargs) { 675 for (i = nargs; i < function->nargs; i++) { 676 if (function->vararg && (i + 1) == function->nargs) 677 uc_vm_stack_push(vm, ucv_array_new_length(vm, 0)); 678 else 679 uc_vm_stack_push(vm, NULL); 680 } 681 } 682 683 /* more arguments on stack than function expects... */ 684 else if (nargs > function->nargs - function->vararg) { 685 /* is a vararg function => pass excess args as array */ 686 if (function->vararg) { 687 ellip = ucv_array_new_length(vm, nargs - (function->nargs - 1)); 688 689 for (i = function->nargs; i <= nargs; i++) 690 ucv_array_push(ellip, uc_vm_stack_peek(vm, nargs - i)); 691 692 for (i = function->nargs; i <= nargs; i++) 693 uc_vm_stack_pop(vm); 694 695 uc_vm_stack_push(vm, ellip); 696 } 697 698 /* static amount of args => drop excess values */ 699 else { 700 for (i = function->nargs; i < nargs; i++) 701 ucv_put(uc_vm_stack_pop(vm)); 702 } 703 } 704 705 frame = uc_vector_push(&vm->callframes, { 706 .stackframe = stackoff, 707 .cfunction = NULL, 708 .closure = closure, 709 .ctx = ctx, 710 .ip = function->chunk.entries, 711 .mcall = mcall, 712 .strict = function->strict 713 }); 714 715 if (vm->trace) 716 uc_vm_frame_dump(vm, frame); 717 718 return true; 719 } 720 721 static uc_source_t *last_source = NULL; 722 static size_t last_srcpos = 0; 723 724 static void 725 uc_dump_insn(uc_vm_t *vm, uint8_t *pos, uc_vm_insn_t insn) 726 { 727 uc_callframe_t *frame = uc_vm_current_frame(vm); 728 uc_chunk_t *chunk = uc_vm_frame_chunk(frame); 729 uc_stringbuf_t *buf = NULL; 730 uc_value_t *cnst = NULL; 731 uc_source_t *source; 732 int8_t argtype; 733 size_t srcpos; 734 735 srcpos = uc_program_function_srcpos(frame->closure->function, pos - chunk->entries); 736 source = uc_vm_frame_source(frame); 737 738 if (last_srcpos == 0 || last_source != source || srcpos != last_srcpos) { 739 buf = xprintbuf_new(); 740 741 uc_source_context_format(buf, source, srcpos, true); 742 fwrite(buf->buf, 1, printbuf_length(buf), stderr); 743 printbuf_free(buf); 744 745 last_source = source; 746 last_srcpos = srcpos; 747 } 748 749 fprintf(stderr, "%08zx %s", pos - chunk->entries, 750 uc_vm_insn_to_name(insn)); 751 752 argtype = uc_vm_insn_to_argtype(insn); 753 754 switch (argtype) { 755 case 0: 756 break; 757 758 case -1: 759 fprintf(stderr, " {%s%hhd}", vm->arg.s8 < 0 ? "" : "+", vm->arg.s8); 760 break; 761 762 case -2: 763 fprintf(stderr, " {%c0x%hx}", 764 vm->arg.s16 < 0 ? '-' : '+', 765 (uint16_t)(vm->arg.s16 < 0 ? -vm->arg.s16 : vm->arg.s16)); 766 break; 767 768 case -4: 769 fprintf(stderr, " {%c0x%x}", 770 vm->arg.s32 < 0 ? '-' : '+', 771 (uint32_t)(vm->arg.s32 < 0 ? -vm->arg.s32 : vm->arg.s32)); 772 break; 773 774 case 1: 775 fprintf(stderr, " {%hhu}", vm->arg.u8); 776 break; 777 778 case 2: 779 fprintf(stderr, " {0x%hx}", vm->arg.u16); 780 break; 781 782 case 4: 783 fprintf(stderr, " {0x%x}", vm->arg.u32); 784 break; 785 786 default: 787 fprintf(stderr, " (unknown operand format: %" PRId8 ")", argtype); 788 break; 789 } 790 791 switch (insn) { 792 case I_LOAD: 793 case I_LVAR: 794 case I_SVAR: 795 cnst = uc_program_get_constant(uc_vm_frame_program(uc_vector_last(&vm->callframes)), vm->arg.u32); 796 797 fprintf(stderr, "\t; %s", 798 cnst ? uc_vm_format_val(vm, cnst) : "(?)"); 799 800 ucv_put(cnst); 801 break; 802 803 case I_LLOC: 804 case I_LUPV: 805 case I_SLOC: 806 case I_SUPV: 807 cnst = uc_chunk_debug_get_variable(chunk, pos - chunk->entries, vm->arg.u32, (insn == I_LUPV || insn == I_SUPV)); 808 809 fprintf(stderr, "\t; %s", 810 cnst ? uc_vm_format_val(vm, cnst) : "(?)"); 811 812 ucv_put(cnst); 813 break; 814 815 case I_ULOC: 816 case I_UUPV: 817 cnst = uc_chunk_debug_get_variable(chunk, pos - chunk->entries, vm->arg.u32 & 0x00ffffff, (insn == I_UUPV)); 818 /* fall through */ 819 820 case I_UVAR: 821 if (!cnst) 822 cnst = uc_program_get_constant(uc_vm_frame_program(uc_vector_last(&vm->callframes)), vm->arg.u32 & 0x00ffffff); 823 824 fprintf(stderr, "\t; %s (%s)", 825 cnst ? uc_vm_format_val(vm, cnst) : "(?)", 826 uc_vm_insn_to_name(vm->arg.u32 >> 24)); 827 828 ucv_put(cnst); 829 break; 830 831 case I_UVAL: 832 fprintf(stderr, "\t; (%s)", uc_vm_insn_to_name(vm->arg.u8)); 833 break; 834 835 default: 836 break; 837 } 838 839 fprintf(stderr, "\n"); 840 } 841 842 static uc_value_t * 843 uc_vm_exception_tostring(uc_vm_t *vm, size_t nargs) 844 { 845 uc_callframe_t *frame = uc_vm_current_frame(vm); 846 uc_value_t *message = ucv_object_get(frame->ctx, "message", NULL); 847 848 return message ? ucv_get(message) : ucv_string_new("Exception"); 849 } 850 851 uc_value_t * 852 uc_vm_exception_object(uc_vm_t *vm) 853 { 854 uc_exception_type_t type = vm->exception.type; 855 const char *message = vm->exception.message; 856 uc_value_t *stacktrace = vm->exception.stacktrace; 857 uc_value_t *exception_prototype = uc_vm_registry_get(vm, "vm.exception.proto"); 858 uc_value_t *exo; 859 860 if (exception_prototype == NULL) { 861 exception_prototype = ucv_object_new(vm); 862 863 ucv_object_add(exception_prototype, "tostring", 864 ucv_cfunction_new("tostring", uc_vm_exception_tostring)); 865 866 uc_vm_registry_set(vm, "vm.exception.proto", exception_prototype); 867 } 868 869 exo = ucv_object_new(vm); 870 871 ucv_object_add(exo, "type", ucv_string_new(exception_type_strings[type])); 872 ucv_object_add(exo, "message", ucv_string_new(message)); 873 ucv_object_add(exo, "stacktrace", ucv_get(stacktrace)); 874 875 ucv_prototype_set(exo, ucv_get(exception_prototype)); 876 877 return exo; 878 } 879 880 static void 881 uc_vm_clear_exception(uc_vm_t *vm) 882 { 883 vm->exception.type = EXCEPTION_NONE; 884 885 ucv_put(vm->exception.stacktrace); 886 vm->exception.stacktrace = NULL; 887 888 free(vm->exception.message); 889 vm->exception.message = NULL; 890 } 891 892 static bool 893 uc_vm_handle_exception(uc_vm_t *vm) 894 { 895 uc_callframe_t *frame = NULL; 896 uc_chunk_t *chunk = NULL; 897 uc_value_t *exo; 898 size_t i, pos; 899 900 if (vm->callframes.count) 901 frame = uc_vm_current_frame(vm); 902 903 if (!frame || !frame->closure) 904 return false; 905 906 chunk = uc_vm_frame_chunk(frame); 907 pos = frame->ip - chunk->entries; 908 909 /* iterate the known exception ranges, see if the current ip falls into any of them */ 910 for (i = 0; i < chunk->ehranges.count; i++) { 911 /* skip nonmatching ranges */ 912 if (pos < chunk->ehranges.entries[i].from || 913 pos >= chunk->ehranges.entries[i].to) 914 continue; 915 916 /* we found a matching range... first unwind stack */ 917 while (vm->stack.count > frame->stackframe + chunk->ehranges.entries[i].slot) 918 ucv_put(uc_vm_stack_pop(vm)); 919 920 /* prepare exception object and expose it to user handler code */ 921 exo = uc_vm_exception_object(vm); 922 923 uc_vm_stack_push(vm, exo); 924 925 /* reset exception information */ 926 uc_vm_clear_exception(vm); 927 928 /* jump to exception handler */ 929 if (chunk->ehranges.entries[i].target >= chunk->count) { 930 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, "jump target out of range"); 931 return false; 932 } 933 934 #if 0 935 if (vm->trace && chunk->entries + chunk->ehranges.entries[i].target > frame->ip) { 936 while (frame->ip < chunk->entries + chunk->ehranges.entries[i].target) { 937 fprintf(stderr, "(eh:skip) [%p:%zu] ", chunk, frame->ip - chunk->entries); 938 uc_dump_insn(vm, frame->ip, uc_vm_decode_insn(vm, frame, chunk)); 939 } 940 } 941 #endif 942 943 frame->ip = chunk->entries + chunk->ehranges.entries[i].target; 944 945 return true; 946 } 947 948 return false; 949 } 950 951 static uc_value_t * 952 uc_vm_capture_stacktrace(uc_vm_t *vm, size_t i) 953 { 954 uc_value_t *stacktrace, *entry, *last = NULL; 955 uc_function_t *function; 956 uc_callframe_t *frame; 957 uc_source_t *source; 958 size_t off, srcpos; 959 char *name; 960 961 stacktrace = ucv_array_new(vm); 962 963 for (; i > 0; i--) { 964 frame = &vm->callframes.entries[i - 1]; 965 entry = ucv_object_new(vm); 966 967 if (frame->closure) { 968 function = frame->closure->function; 969 source = uc_program_function_source(function); 970 971 off = (frame->ip - uc_vm_frame_chunk(frame)->entries) - 1; 972 srcpos = uc_program_function_srcpos(function, off); 973 974 ucv_object_add(entry, "filename", ucv_string_new(source->filename)); 975 ucv_object_add(entry, "line", ucv_int64_new(uc_source_get_line(source, &srcpos))); 976 ucv_object_add(entry, "byte", ucv_int64_new(srcpos)); 977 } 978 979 if (i > 1) { 980 if (frame->closure) { 981 if (frame->closure->function->name[0]) 982 name = frame->closure->function->name; 983 else if (frame->closure->is_arrow) 984 name = "[arrow function]"; 985 else 986 name = "[anonymous function]"; 987 } 988 else { 989 name = frame->cfunction->name; 990 } 991 992 ucv_object_add(entry, "function", ucv_string_new(name)); 993 } 994 995 if (!ucv_is_equal(last, entry)) { 996 ucv_array_push(stacktrace, entry); 997 last = entry; 998 } 999 else { 1000 ucv_put(entry); 1001 } 1002 } 1003 1004 return stacktrace; 1005 } 1006 1007 static uc_value_t * 1008 uc_vm_get_error_context(uc_vm_t *vm) 1009 { 1010 size_t offset, i, byte, line; 1011 uc_value_t *stacktrace; 1012 uc_callframe_t *frame; 1013 uc_stringbuf_t *buf; 1014 uc_chunk_t *chunk; 1015 1016 /* skip to first non-native function call frame */ 1017 for (i = vm->callframes.count; i > 1; i--) 1018 if (vm->callframes.entries[i - 1].closure) 1019 break; 1020 1021 frame = &vm->callframes.entries[i - 1]; 1022 1023 if (!frame->closure) 1024 return NULL; 1025 1026 chunk = uc_vm_frame_chunk(frame); 1027 offset = uc_program_function_srcpos(frame->closure->function, (frame->ip - chunk->entries) - 1); 1028 stacktrace = uc_vm_capture_stacktrace(vm, i); 1029 1030 buf = ucv_stringbuf_new(); 1031 1032 byte = offset; 1033 line = uc_source_get_line(uc_program_function_source(frame->closure->function), &byte); 1034 1035 if (line) 1036 uc_error_context_format(buf, uc_vm_frame_source(frame), stacktrace, offset); 1037 else if (frame->ip != chunk->entries) 1038 ucv_stringbuf_printf(buf, "At instruction %zu", (frame->ip - chunk->entries) - 1); 1039 else 1040 ucv_stringbuf_append(buf, "At start of program"); 1041 1042 ucv_object_add(ucv_array_get(stacktrace, 0), "context", ucv_stringbuf_finish(buf)); 1043 1044 return stacktrace; 1045 } 1046 1047 void __attribute__((format(printf, 3, 0))) 1048 uc_vm_raise_exception(uc_vm_t *vm, uc_exception_type_t type, const char *fmt, ...) 1049 { 1050 va_list ap; 1051 1052 vm->exception.type = type; 1053 1054 free(vm->exception.message); 1055 1056 va_start(ap, fmt); 1057 xvasprintf(&vm->exception.message, fmt, ap); 1058 va_end(ap); 1059 1060 ucv_put(vm->exception.stacktrace); 1061 vm->exception.stacktrace = uc_vm_get_error_context(vm); 1062 } 1063 1064 static bool 1065 uc_vm_test_strict_equality(uc_value_t *v1, uc_value_t *v2, bool nan_equal) 1066 { 1067 uc_type_t t1 = ucv_type(v1); 1068 uc_type_t t2 = ucv_type(v2); 1069 double d1, d2; 1070 1071 if (t1 != t2) 1072 return false; 1073 1074 switch (t1) { 1075 case UC_DOUBLE: 1076 d1 = ((uc_double_t *)v1)->dbl; 1077 d2 = ((uc_double_t *)v2)->dbl; 1078 1079 if (isnan(d1) && isnan(d2)) 1080 return nan_equal; 1081 1082 return (d1 == d2); 1083 1084 case UC_NULL: 1085 case UC_BOOLEAN: 1086 case UC_INTEGER: 1087 case UC_STRING: 1088 return ucv_is_equal(v1, v2); 1089 1090 default: 1091 return (v1 == v2); 1092 } 1093 } 1094 1095 1096 static void 1097 uc_vm_insn_load(uc_vm_t *vm, uc_vm_insn_t insn) 1098 { 1099 switch (insn) { 1100 case I_LOAD: 1101 uc_vm_stack_push(vm, uc_program_get_constant(uc_vm_current_program(vm), vm->arg.u32)); 1102 break; 1103 1104 case I_LOAD8: 1105 uc_vm_stack_push(vm, ucv_uint64_new(vm->arg.u8)); 1106 break; 1107 1108 case I_LOAD16: 1109 uc_vm_stack_push(vm, ucv_uint64_new(vm->arg.u16)); 1110 break; 1111 1112 case I_LOAD32: 1113 uc_vm_stack_push(vm, ucv_uint64_new(vm->arg.u32)); 1114 break; 1115 1116 default: 1117 break; 1118 } 1119 } 1120 1121 static void 1122 uc_vm_insn_load_regexp(uc_vm_t *vm, uc_vm_insn_t insn) 1123 { 1124 uc_value_t *re, *jstr = uc_program_get_constant(uc_vm_current_program(vm), vm->arg.u32); 1125 bool icase = false, newline = false, global = false; 1126 char *str, *err = NULL; 1127 1128 if (ucv_type(jstr) != UC_STRING || ucv_string_length(jstr) < 2) { 1129 uc_vm_stack_push(vm, NULL); 1130 ucv_put(jstr); 1131 1132 return; 1133 } 1134 1135 str = ucv_string_get(jstr); 1136 1137 global = (*str & (1 << 0)); 1138 icase = (*str & (1 << 1)); 1139 newline = (*str & (1 << 2)); 1140 1141 re = ucv_regexp_new(++str, icase, newline, global, &err); 1142 1143 ucv_put(jstr); 1144 1145 if (re) 1146 uc_vm_stack_push(vm, re); 1147 else 1148 uc_vm_raise_exception(vm, EXCEPTION_SYNTAX, "%s", err); 1149 1150 free(err); 1151 } 1152 1153 static void 1154 uc_vm_insn_load_null(uc_vm_t *vm, uc_vm_insn_t insn) 1155 { 1156 uc_vm_stack_push(vm, NULL); 1157 } 1158 1159 static void 1160 uc_vm_insn_load_bool(uc_vm_t *vm, uc_vm_insn_t insn) 1161 { 1162 uc_vm_stack_push(vm, ucv_boolean_new(insn == I_LTRUE)); 1163 } 1164 1165 static void 1166 uc_vm_insn_load_var(uc_vm_t *vm, uc_vm_insn_t insn) 1167 { 1168 uc_value_t *name, *val = NULL; 1169 uc_value_t *scope, *next; 1170 bool found; 1171 1172 scope = vm->globals; 1173 name = uc_program_get_constant(uc_vm_current_program(vm), vm->arg.u32); 1174 1175 while (ucv_type(name) == UC_STRING) { 1176 val = ucv_object_get(scope, ucv_string_get(name), &found); 1177 1178 if (found) 1179 break; 1180 1181 next = ucv_prototype_get(scope); 1182 1183 if (!next) { 1184 if (uc_vm_is_strict(vm)) { 1185 uc_vm_raise_exception(vm, EXCEPTION_REFERENCE, 1186 "access to undeclared variable %s", 1187 ucv_string_get(name)); 1188 } 1189 1190 break; 1191 } 1192 1193 scope = next; 1194 } 1195 1196 ucv_put(name); 1197 1198 uc_vm_stack_push(vm, ucv_get(val)); 1199 } 1200 1201 static void 1202 uc_vm_insn_load_val(uc_vm_t *vm, uc_vm_insn_t insn) 1203 { 1204 uc_value_t *k = uc_vm_stack_pop(vm); 1205 uc_value_t *v = uc_vm_stack_pop(vm); 1206 1207 switch (ucv_type(v)) { 1208 case UC_RESOURCE: 1209 case UC_OBJECT: 1210 case UC_ARRAY: 1211 uc_vm_stack_push(vm, ucv_key_get(vm, v, k)); 1212 break; 1213 1214 default: 1215 uc_vm_raise_exception(vm, EXCEPTION_REFERENCE, 1216 "left-hand side expression is %s", 1217 v ? "not an array or object" : "null"); 1218 1219 break; 1220 } 1221 1222 ucv_put(k); 1223 ucv_put(v); 1224 } 1225 1226 static void 1227 uc_vm_insn_peek_val(uc_vm_t *vm, uc_vm_insn_t insn) 1228 { 1229 uc_value_t *k = uc_vm_stack_pop(vm); 1230 uc_value_t *v = uc_vm_stack_peek(vm, 0); 1231 1232 switch (ucv_type(v)) { 1233 case UC_RESOURCE: 1234 case UC_OBJECT: 1235 case UC_ARRAY: 1236 uc_vm_stack_push(vm, ucv_key_get(vm, v, k)); 1237 break; 1238 1239 default: 1240 uc_vm_raise_exception(vm, EXCEPTION_REFERENCE, 1241 "left-hand side expression is %s", 1242 v ? "not an array or object" : "null"); 1243 1244 break; 1245 } 1246 1247 ucv_put(k); 1248 } 1249 1250 static void 1251 uc_vm_insn_load_upval(uc_vm_t *vm, uc_vm_insn_t insn) 1252 { 1253 uc_callframe_t *frame = uc_vm_current_frame(vm); 1254 uc_upvalref_t *ref = frame->closure->upvals[vm->arg.u32]; 1255 1256 if (ref->closed) 1257 uc_vm_stack_push(vm, ucv_get(ref->value)); 1258 else 1259 uc_vm_stack_push(vm, ucv_get(vm->stack.entries[ref->slot])); 1260 } 1261 1262 static void 1263 uc_vm_insn_load_local(uc_vm_t *vm, uc_vm_insn_t insn) 1264 { 1265 uc_callframe_t *frame = uc_vm_current_frame(vm); 1266 1267 uc_vm_stack_push(vm, ucv_get(vm->stack.entries[frame->stackframe + vm->arg.u32])); 1268 } 1269 1270 static uc_upvalref_t * 1271 uc_vm_capture_upval(uc_vm_t *vm, size_t slot) 1272 { 1273 uc_upvalref_t *curr = vm->open_upvals; 1274 uc_upvalref_t *prev = NULL; 1275 uc_upvalref_t *created; 1276 char *s; 1277 1278 while (curr && curr->slot > slot) { 1279 prev = curr; 1280 curr = curr->next; 1281 } 1282 1283 if (curr && curr->slot == slot) { 1284 if (vm->trace) { 1285 s = ucv_to_string(NULL, vm->stack.entries[slot]); 1286 fprintf(stderr, " {+%zu} <%p> %s\n", slot, (void *)curr, s); 1287 free(s); 1288 } 1289 1290 return curr; 1291 } 1292 1293 created = (uc_upvalref_t *)ucv_upvalref_new(slot); 1294 created->next = curr; 1295 1296 if (vm->trace) { 1297 s = ucv_to_string(NULL, vm->stack.entries[slot]); 1298 fprintf(stderr, " {*%zu} <%p> %s\n", slot, (void *)created, s); 1299 free(s); 1300 } 1301 1302 if (prev) 1303 prev->next = created; 1304 else 1305 vm->open_upvals = created; 1306 1307 return created; 1308 } 1309 1310 static void 1311 uc_vm_close_upvals(uc_vm_t *vm, size_t slot) 1312 { 1313 uc_upvalref_t *ref; 1314 1315 while (vm->open_upvals && vm->open_upvals->slot >= slot) { 1316 ref = vm->open_upvals; 1317 ref->value = ucv_get(vm->stack.entries[ref->slot]); 1318 ref->closed = true; 1319 1320 if (vm->trace) { 1321 fprintf(stderr, " {!%zu} <%p> %s\n", ref->slot, 1322 (void *)ref, 1323 uc_vm_format_val(vm, ref->value)); 1324 } 1325 1326 vm->open_upvals = ref->next; 1327 ucv_put(&ref->header); 1328 } 1329 } 1330 1331 static void 1332 uc_vm_insn_load_closure(uc_vm_t *vm, uc_vm_insn_t insn) 1333 { 1334 uc_callframe_t *frame = uc_vm_current_frame(vm); 1335 uc_function_t *function = uc_program_function_load(uc_vm_current_program(vm), vm->arg.u32); 1336 uc_closure_t *closure = (uc_closure_t *)ucv_closure_new(vm, function, insn == I_ARFN); 1337 volatile int32_t uv; 1338 size_t i; 1339 1340 uc_vm_stack_push(vm, &closure->header); 1341 1342 if (function->module) 1343 return; 1344 1345 for (i = 0; i < function->nupvals; i++) { 1346 uv = ( 1347 frame->ip[0] * 0x1000000 + 1348 frame->ip[1] * 0x10000 + 1349 frame->ip[2] * 0x100 + 1350 frame->ip[3] 1351 ) - 0x7fffffff; 1352 1353 if (uv < 0) 1354 closure->upvals[i] = uc_vm_capture_upval(vm, frame->stackframe - (uv + 1)); 1355 else 1356 closure->upvals[i] = frame->closure->upvals[uv]; 1357 1358 ucv_get(&closure->upvals[i]->header); 1359 1360 frame->ip += 4; 1361 } 1362 } 1363 1364 static void 1365 uc_vm_insn_store_var(uc_vm_t *vm, uc_vm_insn_t insn) 1366 { 1367 uc_value_t *name, *v = uc_vm_stack_pop(vm); 1368 uc_value_t *scope, *next; 1369 bool found; 1370 1371 scope = vm->globals; 1372 name = uc_program_get_constant(uc_vm_current_program(vm), vm->arg.u32); 1373 1374 while (ucv_type(name) == UC_STRING) { 1375 ucv_object_get(scope, ucv_string_get(name), &found); 1376 1377 if (found) 1378 break; 1379 1380 next = ucv_prototype_get(scope); 1381 1382 if (!next) { 1383 if (uc_vm_is_strict(vm)) { 1384 uc_vm_raise_exception(vm, EXCEPTION_REFERENCE, 1385 "access to undeclared variable %s", 1386 ucv_string_get(name)); 1387 } 1388 1389 break; 1390 } 1391 1392 scope = next; 1393 } 1394 1395 if (scope && ucv_type(name) == UC_STRING) 1396 ucv_object_add(scope, ucv_string_get(name), ucv_get(v)); 1397 1398 ucv_put(name); 1399 uc_vm_stack_push(vm, v); 1400 } 1401 1402 static bool 1403 assert_mutable_value(uc_vm_t *vm, uc_value_t *val) 1404 { 1405 if (ucv_is_constant(val)) { 1406 uc_vm_stack_push(vm, NULL); 1407 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 1408 "%s value is immutable", 1409 ucv_typename(val)); 1410 1411 return false; 1412 } 1413 1414 return true; 1415 } 1416 1417 static void 1418 uc_vm_insn_store_val(uc_vm_t *vm, uc_vm_insn_t insn) 1419 { 1420 uc_value_t *v = uc_vm_stack_pop(vm); 1421 uc_value_t *k = uc_vm_stack_pop(vm); 1422 uc_value_t *o = uc_vm_stack_pop(vm); 1423 1424 switch (ucv_type(o)) { 1425 case UC_OBJECT: 1426 case UC_ARRAY: 1427 if (assert_mutable_value(vm, o)) 1428 uc_vm_stack_push(vm, ucv_key_set(vm, o, k, v)); 1429 1430 break; 1431 1432 default: 1433 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 1434 "attempt to set property on %s value", 1435 ucv_typename(o)); 1436 } 1437 1438 ucv_put(o); 1439 ucv_put(k); 1440 } 1441 1442 static void 1443 uc_vm_insn_store_upval(uc_vm_t *vm, uc_vm_insn_t insn) 1444 { 1445 uc_callframe_t *frame = uc_vm_current_frame(vm); 1446 uc_upvalref_t *ref = frame->closure->upvals[vm->arg.u32]; 1447 uc_value_t *val = ucv_get(uc_vm_stack_peek(vm, 0)); 1448 1449 if (ref->closed) { 1450 ucv_put(ref->value); 1451 ref->value = val; 1452 } 1453 else { 1454 uc_vm_stack_set(vm, ref->slot, val); 1455 } 1456 } 1457 1458 static void 1459 uc_vm_insn_store_local(uc_vm_t *vm, uc_vm_insn_t insn) 1460 { 1461 uc_callframe_t *frame = uc_vm_current_frame(vm); 1462 uc_value_t *val = ucv_get(uc_vm_stack_peek(vm, 0)); 1463 1464 uc_vm_stack_set(vm, frame->stackframe + vm->arg.u32, val); 1465 } 1466 1467 static int64_t 1468 int64(uc_value_t *nv, uint64_t *u64) 1469 { 1470 int64_t n; 1471 1472 n = ucv_int64_get(nv); 1473 *u64 = 0; 1474 1475 if (errno == ERANGE) { 1476 n = INT64_MAX; 1477 *u64 = ucv_uint64_get(nv); 1478 } 1479 1480 return n; 1481 } 1482 1483 static uint64_t 1484 abs64(int64_t n) 1485 { 1486 if (n == INT64_MIN) 1487 return 0x8000000000000000ULL; 1488 1489 if (n < 0) 1490 return -n; 1491 1492 return n; 1493 } 1494 1495 1496 static uc_value_t * 1497 uc_vm_value_bitop(uc_vm_t *vm, uc_vm_insn_t operation, uc_value_t *value, uc_value_t *operand) 1498 { 1499 uc_value_t *nv1, *nv2, *rv = NULL; 1500 uint64_t u1, u2; 1501 int64_t n1, n2; 1502 1503 nv1 = ucv_to_number(value); 1504 nv2 = ucv_to_number(operand); 1505 1506 n1 = int64(nv1, &u1); 1507 n2 = int64(nv2, &u2); 1508 1509 if (n1 < 0 || n2 < 0) { 1510 switch (operation) { 1511 case I_LSHIFT: 1512 rv = ucv_int64_new(n1 << n2); 1513 break; 1514 1515 case I_RSHIFT: 1516 rv = ucv_int64_new(n1 >> n2); 1517 break; 1518 1519 case I_BAND: 1520 rv = ucv_int64_new(n1 & n2); 1521 break; 1522 1523 case I_BXOR: 1524 rv = ucv_int64_new(n1 ^ n2); 1525 break; 1526 1527 case I_BOR: 1528 rv = ucv_int64_new(n1 | n2); 1529 break; 1530 1531 default: 1532 break; 1533 } 1534 } 1535 else { 1536 if (!u1) u1 = (uint64_t)n1; 1537 if (!u2) u2 = (uint64_t)n2; 1538 1539 switch (operation) { 1540 case I_LSHIFT: 1541 rv = ucv_uint64_new(u1 << (u2 % (sizeof(uint64_t) * CHAR_BIT))); 1542 break; 1543 1544 case I_RSHIFT: 1545 rv = ucv_uint64_new(u1 >> (u2 % (sizeof(uint64_t) * CHAR_BIT))); 1546 break; 1547 1548 case I_BAND: 1549 rv = ucv_uint64_new(u1 & u2); 1550 break; 1551 1552 case I_BXOR: 1553 rv = ucv_uint64_new(u1 ^ u2); 1554 break; 1555 1556 case I_BOR: 1557 rv = ucv_uint64_new(u1 | u2); 1558 break; 1559 1560 default: 1561 break; 1562 } 1563 } 1564 1565 ucv_put(nv1); 1566 ucv_put(nv2); 1567 1568 return rv; 1569 } 1570 1571 static uc_value_t * 1572 uc_vm_string_concat(uc_vm_t *vm, uc_value_t *v1, uc_value_t *v2) 1573 { 1574 char buf[sizeof(void *)], *s1, *s2, *str; 1575 uc_value_t *ustr; 1576 uc_stringbuf_t *sbuf; 1577 size_t l1, l2; 1578 1579 /* optimize cases for string+string concat... */ 1580 if (ucv_type(v1) == UC_STRING && ucv_type(v2) == UC_STRING) { 1581 s1 = ucv_string_get(v1); 1582 s2 = ucv_string_get(v2); 1583 l1 = ucv_string_length(v1); 1584 l2 = ucv_string_length(v2); 1585 1586 /* ... result fits into a tagged pointer */ 1587 if (l1 + l2 + 1 < sizeof(buf)) { 1588 memcpy(&buf[0], s1, l1); 1589 memcpy(&buf[l1], s2, l2); 1590 1591 return ucv_string_new_length(buf, l1 + l2); 1592 } 1593 else { 1594 ustr = ucv_string_alloc(&str, l1 + l2); 1595 memcpy(&str[0], s1, l1); 1596 memcpy(&str[l1], s2, l2); 1597 1598 return ustr; 1599 } 1600 } 1601 1602 sbuf = ucv_stringbuf_new(); 1603 1604 ucv_to_stringbuf(vm, sbuf, v1, false); 1605 ucv_to_stringbuf(vm, sbuf, v2, false); 1606 1607 return ucv_stringbuf_finish(sbuf); 1608 } 1609 1610 static uint64_t 1611 upow64(uint64_t base, uint64_t exponent) 1612 { 1613 uint64_t result = 1; 1614 1615 while (exponent) { 1616 if (exponent & 1) 1617 result *= base; 1618 1619 exponent >>= 1; 1620 base *= base; 1621 } 1622 1623 return result; 1624 } 1625 1626 static uc_value_t * 1627 uc_vm_value_arith(uc_vm_t *vm, uc_vm_insn_t operation, uc_value_t *value, uc_value_t *operand) 1628 { 1629 uc_value_t *nv1, *nv2, *rv = NULL; 1630 uint64_t u1, u2; 1631 int64_t n1, n2; 1632 double d1, d2; 1633 1634 if (operation == I_LSHIFT || operation == I_RSHIFT || 1635 operation == I_BAND || operation == I_BXOR || operation == I_BOR) 1636 return uc_vm_value_bitop(vm, operation, value, operand); 1637 1638 if (operation == I_ADD && (ucv_type(value) == UC_STRING || ucv_type(operand) == UC_STRING)) 1639 return uc_vm_string_concat(vm, value, operand); 1640 1641 nv1 = ucv_to_number(value); 1642 nv2 = ucv_to_number(operand); 1643 1644 /* any operation involving NaN results in NaN */ 1645 if (!nv1 || !nv2) { 1646 ucv_put(nv1); 1647 ucv_put(nv2); 1648 1649 return ucv_double_new(NAN); 1650 } 1651 if (ucv_type(nv1) == UC_DOUBLE || ucv_type(nv2) == UC_DOUBLE) { 1652 d1 = ucv_double_get(nv1); 1653 d2 = ucv_double_get(nv2); 1654 1655 switch (operation) { 1656 case I_ADD: 1657 case I_PLUS: 1658 rv = ucv_double_new(d1 + d2); 1659 break; 1660 1661 case I_SUB: 1662 case I_MINUS: 1663 rv = ucv_double_new(d1 - d2); 1664 break; 1665 1666 case I_MUL: 1667 rv = ucv_double_new(d1 * d2); 1668 break; 1669 1670 case I_DIV: 1671 if (d2 == 0.0) 1672 rv = ucv_double_new(INFINITY); 1673 else if (isnan(d2)) 1674 rv = ucv_double_new(NAN); 1675 else if (!isfinite(d2)) 1676 rv = ucv_double_new(isfinite(d1) ? 0.0 : NAN); 1677 else 1678 rv = ucv_double_new(d1 / d2); 1679 1680 break; 1681 1682 case I_MOD: 1683 rv = ucv_double_new(fmod(d1, d2)); 1684 break; 1685 1686 case I_EXP: 1687 rv = ucv_double_new(pow(d1, d2)); 1688 break; 1689 1690 default: 1691 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, 1692 "undefined arithmetic operation %d", 1693 operation); 1694 break; 1695 } 1696 } 1697 else { 1698 n1 = int64(nv1, &u1); 1699 n2 = int64(nv2, &u2); 1700 1701 switch (operation) { 1702 case I_ADD: 1703 case I_PLUS: 1704 if (n1 < 0 || n2 < 0) { 1705 if (u1) 1706 rv = ucv_uint64_new(u1 - abs64(n2)); 1707 else if (u2) 1708 rv = ucv_uint64_new(u2 - abs64(n1)); 1709 else 1710 rv = ucv_int64_new(n1 + n2); 1711 } 1712 else { 1713 if (!u1) u1 = (uint64_t)n1; 1714 if (!u2) u2 = (uint64_t)n2; 1715 1716 rv = ucv_uint64_new(u1 + u2); 1717 } 1718 1719 break; 1720 1721 case I_SUB: 1722 case I_MINUS: 1723 if (n1 < 0 && n2 < 0) { 1724 if (n1 > n2) 1725 rv = ucv_uint64_new(abs64(n2) - abs64(n1)); 1726 else 1727 rv = ucv_int64_new(n1 - n2); 1728 } 1729 else if (n1 >= 0 && n2 >= 0) { 1730 if (!u1) u1 = (uint64_t)n1; 1731 if (!u2) u2 = (uint64_t)n2; 1732 1733 if (u2 > u1) 1734 rv = ucv_int64_new(-(u2 - u1)); 1735 else 1736 rv = ucv_uint64_new(u1 - u2); 1737 } 1738 else if (n1 >= 0) { 1739 if (!u1) u1 = (uint64_t)n1; 1740 1741 rv = ucv_uint64_new(u1 + abs64(n2)); 1742 } 1743 else { 1744 rv = ucv_int64_new(n1 - n2); 1745 } 1746 1747 break; 1748 1749 case I_MUL: 1750 if (n1 < 0 && n2 < 0) { 1751 rv = ucv_uint64_new(abs64(n1) * abs64(n2)); 1752 } 1753 else if (n1 >= 0 && n2 >= 0) { 1754 if (!u1) u1 = (uint64_t)n1; 1755 if (!u2) u2 = (uint64_t)n2; 1756 1757 rv = ucv_uint64_new(u1 * u2); 1758 } 1759 else { 1760 rv = ucv_int64_new(n1 * n2); 1761 } 1762 1763 break; 1764 1765 case I_DIV: 1766 if (n2 == 0) { 1767 rv = ucv_double_new(INFINITY); 1768 } 1769 else if (n1 < 0 || n2 < 0) { 1770 rv = ucv_int64_new(n1 / n2); 1771 } 1772 else { 1773 if (!u1) u1 = (uint64_t)n1; 1774 if (!u2) u2 = (uint64_t)n2; 1775 1776 rv = ucv_uint64_new(u1 / u2); 1777 } 1778 1779 break; 1780 1781 case I_MOD: 1782 if (n2 == 0) { 1783 rv = ucv_double_new(NAN); 1784 } 1785 else if (n1 < 0 || n2 < 0) { 1786 rv = ucv_int64_new(n1 % n2); 1787 } 1788 else { 1789 if (!u1) u1 = (uint64_t)n1; 1790 if (!u2) u2 = (uint64_t)n2; 1791 1792 rv = ucv_uint64_new(u1 % u2); 1793 } 1794 1795 break; 1796 1797 case I_EXP: 1798 if (n1 < 0 || n2 < 0) { 1799 if (n1 < 0 && n2 < 0) 1800 rv = ucv_double_new(-(1.0 / (double)upow64(abs64(n1), abs64(n2)))); 1801 else if (n2 < 0) 1802 rv = ucv_double_new(1.0 / (double)upow64(abs64(n1), abs64(n2))); 1803 else 1804 rv = ucv_int64_new(-upow64(abs64(n1), abs64(n2))); 1805 } 1806 else { 1807 if (!u1) u1 = (uint64_t)n1; 1808 if (!u2) u2 = (uint64_t)n2; 1809 1810 rv = ucv_uint64_new(upow64(u1, u2)); 1811 } 1812 1813 break; 1814 1815 default: 1816 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, 1817 "undefined arithmetic operation %d", 1818 operation); 1819 break; 1820 } 1821 } 1822 1823 ucv_put(nv1); 1824 ucv_put(nv2); 1825 1826 return rv; 1827 } 1828 1829 static void 1830 uc_vm_insn_update_var(uc_vm_t *vm, uc_vm_insn_t insn) 1831 { 1832 uc_value_t *name, *val = NULL, *inc = uc_vm_stack_pop(vm); 1833 uc_value_t *scope, *next; 1834 bool found; 1835 1836 scope = vm->globals; 1837 name = uc_program_get_constant(uc_vm_current_program(vm), vm->arg.u32 & 0x00FFFFFF); 1838 1839 assert(ucv_type(name) == UC_STRING); 1840 1841 while (true) { 1842 val = ucv_object_get(scope, ucv_string_get(name), &found); 1843 1844 if (found) 1845 break; 1846 1847 next = ucv_prototype_get(scope); 1848 1849 if (!next) { 1850 if (uc_vm_is_strict(vm)) { 1851 uc_vm_raise_exception(vm, EXCEPTION_REFERENCE, 1852 "access to undeclared variable %s", 1853 ucv_string_get(name)); 1854 } 1855 1856 break; 1857 } 1858 1859 scope = next; 1860 } 1861 1862 val = uc_vm_value_arith(vm, vm->arg.u32 >> 24, val, inc); 1863 1864 ucv_object_add(scope, ucv_string_get(name), ucv_get(val)); 1865 uc_vm_stack_push(vm, val); 1866 1867 ucv_put(name); 1868 ucv_put(inc); 1869 } 1870 1871 static void 1872 uc_vm_insn_update_val(uc_vm_t *vm, uc_vm_insn_t insn) 1873 { 1874 uc_value_t *inc = uc_vm_stack_pop(vm); 1875 uc_value_t *k = uc_vm_stack_pop(vm); 1876 uc_value_t *v = uc_vm_stack_pop(vm); 1877 uc_value_t *val = NULL; 1878 1879 switch (ucv_type(v)) { 1880 case UC_OBJECT: 1881 case UC_ARRAY: 1882 if (assert_mutable_value(vm, v)) { 1883 val = ucv_key_get(vm, v, k); 1884 uc_vm_stack_push(vm, ucv_key_set(vm, v, k, uc_vm_value_arith(vm, vm->arg.u8, val, inc))); 1885 } 1886 1887 break; 1888 1889 default: 1890 uc_vm_raise_exception(vm, EXCEPTION_REFERENCE, 1891 "left-hand side expression is %s", 1892 v ? "not an array or object" : "null"); 1893 1894 break; 1895 } 1896 1897 ucv_put(val); 1898 ucv_put(inc); 1899 ucv_put(v); 1900 ucv_put(k); 1901 } 1902 1903 static void 1904 uc_vm_insn_update_upval(uc_vm_t *vm, uc_vm_insn_t insn) 1905 { 1906 uc_callframe_t *frame = uc_vm_current_frame(vm); 1907 size_t slot = vm->arg.u32 & 0x00FFFFFF; 1908 uc_upvalref_t *ref = frame->closure->upvals[slot]; 1909 uc_value_t *inc = uc_vm_stack_pop(vm); 1910 uc_value_t *val; 1911 1912 if (ref->closed) 1913 val = ref->value; 1914 else 1915 val = vm->stack.entries[ref->slot]; 1916 1917 val = uc_vm_value_arith(vm, vm->arg.u32 >> 24, val, inc); 1918 1919 uc_vm_stack_push(vm, val); 1920 1921 ucv_put(inc); 1922 1923 if (ref->closed) { 1924 ucv_put(ref->value); 1925 ref->value = ucv_get(uc_vm_stack_peek(vm, 0)); 1926 } 1927 else { 1928 uc_vm_stack_set(vm, ref->slot, ucv_get(uc_vm_stack_peek(vm, 0))); 1929 } 1930 } 1931 1932 static void 1933 uc_vm_insn_update_local(uc_vm_t *vm, uc_vm_insn_t insn) 1934 { 1935 uc_callframe_t *frame = uc_vm_current_frame(vm); 1936 size_t slot = vm->arg.u32 & 0x00FFFFFF; 1937 uc_value_t *inc = uc_vm_stack_pop(vm); 1938 uc_value_t *val; 1939 1940 val = uc_vm_value_arith(vm, vm->arg.u32 >> 24, 1941 vm->stack.entries[frame->stackframe + slot], inc); 1942 1943 uc_vm_stack_push(vm, val); 1944 1945 ucv_put(inc); 1946 uc_vm_stack_set(vm, frame->stackframe + slot, ucv_get(uc_vm_stack_peek(vm, 0))); 1947 } 1948 1949 static void 1950 uc_vm_insn_narr(uc_vm_t *vm, uc_vm_insn_t insn) 1951 { 1952 uc_value_t *arr = ucv_array_new_length(vm, vm->arg.u32); 1953 1954 uc_vm_stack_push(vm, arr); 1955 } 1956 1957 static void 1958 uc_vm_insn_parr(uc_vm_t *vm, uc_vm_insn_t insn) 1959 { 1960 uc_value_t *arr = uc_vm_stack_peek(vm, vm->arg.u32); 1961 size_t idx; 1962 1963 for (idx = 0; idx < vm->arg.u32; idx++) 1964 ucv_array_push(arr, uc_vm_stack_peek(vm, vm->arg.u32 - idx - 1)); 1965 1966 for (idx = 0; idx < vm->arg.u32; idx++) 1967 uc_vm_stack_pop(vm); 1968 1969 //uc_vm_shrink(state, vm->arg.u32); 1970 } 1971 1972 static void 1973 uc_vm_insn_marr(uc_vm_t *vm, uc_vm_insn_t insn) 1974 { 1975 uc_value_t *src = uc_vm_stack_pop(vm); 1976 uc_value_t *dst = uc_vm_stack_peek(vm, 0); 1977 size_t i; 1978 char *s; 1979 1980 if (ucv_type(src) != UC_ARRAY) { 1981 s = ucv_to_string(vm, src); 1982 uc_vm_raise_exception(vm, EXCEPTION_TYPE, "(%s) is not iterable", s); 1983 ucv_put(src); 1984 free(s); 1985 1986 return; 1987 } 1988 1989 for (i = 0; i < ucv_array_length(src); i++) 1990 ucv_array_push(dst, ucv_get(ucv_array_get(src, i))); 1991 1992 ucv_put(src); 1993 } 1994 1995 static void 1996 uc_vm_insn_nobj(uc_vm_t *vm, uc_vm_insn_t insn) 1997 { 1998 uc_value_t *obj = ucv_object_new(vm); 1999 2000 uc_vm_stack_push(vm, obj); 2001 } 2002 2003 static void 2004 uc_vm_insn_sobj(uc_vm_t *vm, uc_vm_insn_t insn) 2005 { 2006 uc_value_t *obj = uc_vm_stack_peek(vm, vm->arg.u32); 2007 size_t idx; 2008 2009 for (idx = 0; idx < vm->arg.u32; idx += 2) 2010 ucv_key_set(vm, obj, 2011 uc_vm_stack_peek(vm, vm->arg.u32 - idx - 1), 2012 uc_vm_stack_peek(vm, vm->arg.u32 - idx - 2)); 2013 2014 for (idx = 0; idx < vm->arg.u32; idx++) 2015 ucv_put(uc_vm_stack_pop(vm)); 2016 } 2017 2018 static void 2019 uc_vm_insn_mobj(uc_vm_t *vm, uc_vm_insn_t insn) 2020 { 2021 uc_value_t *src = uc_vm_stack_pop(vm); 2022 uc_value_t *dst = uc_vm_stack_peek(vm, 0); 2023 size_t i; 2024 char *s; 2025 2026 switch (ucv_type(src)) { 2027 case UC_OBJECT: 2028 ; /* a label can only be part of a statement and a declaration is not a statement */ 2029 ucv_object_foreach(src, k, v) 2030 ucv_object_add(dst, k, ucv_get(v)); 2031 2032 ucv_put(src); 2033 break; 2034 2035 case json_type_array: 2036 for (i = 0; i < ucv_array_length(src); i++) { 2037 xasprintf(&s, "%zu", i); 2038 ucv_object_add(dst, s, ucv_get(ucv_array_get(src, i))); 2039 free(s); 2040 } 2041 2042 ucv_put(src); 2043 break; 2044 2045 default: 2046 s = ucv_to_string(vm, src); 2047 uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Value (%s) is not iterable", s); 2048 free(s); 2049 2050 break; 2051 } 2052 } 2053 2054 static void 2055 uc_vm_insn_arith(uc_vm_t *vm, uc_vm_insn_t insn) 2056 { 2057 uc_value_t *r2 = uc_vm_stack_pop(vm); 2058 uc_value_t *r1 = uc_vm_stack_pop(vm); 2059 uc_value_t *rv; 2060 2061 rv = uc_vm_value_arith(vm, insn, r1, r2); 2062 2063 ucv_put(r1); 2064 ucv_put(r2); 2065 2066 uc_vm_stack_push(vm, rv); 2067 } 2068 2069 static void 2070 uc_vm_insn_plus_minus(uc_vm_t *vm, uc_vm_insn_t insn) 2071 { 2072 uc_value_t *v = uc_vm_stack_pop(vm), *nv; 2073 bool is_sub = (insn == I_MINUS); 2074 int64_t n; 2075 double d; 2076 2077 if (ucv_type(v) == UC_STRING) { 2078 nv = uc_number_parse(ucv_string_get(v), NULL); 2079 2080 if (nv) { 2081 ucv_put(v); 2082 v = nv; 2083 } 2084 } 2085 2086 switch (ucv_type(v)) { 2087 case UC_INTEGER: 2088 n = ucv_int64_get(v); 2089 2090 /* numeric value is in range 9223372036854775808..18446744073709551615 */ 2091 if (errno == ERANGE) { 2092 if (is_sub) 2093 /* make negation of large numeric value result in smallest negative value */ 2094 uc_vm_stack_push(vm, ucv_int64_new(INT64_MIN)); 2095 else 2096 /* for positive number coercion return value as-is */ 2097 uc_vm_stack_push(vm, ucv_get(v)); 2098 } 2099 2100 /* numeric value is in range -9223372036854775808..9223372036854775807 */ 2101 else { 2102 if (is_sub) { 2103 if (n == INT64_MIN) 2104 /* make negation of minimum value result in maximum signed positive value */ 2105 uc_vm_stack_push(vm, ucv_int64_new(INT64_MAX)); 2106 else 2107 /* for all other values flip the sign */ 2108 uc_vm_stack_push(vm, ucv_int64_new(-n)); 2109 } 2110 else { 2111 /* for positive number coercion return value as-is */ 2112 uc_vm_stack_push(vm, ucv_get(v)); 2113 } 2114 } 2115 2116 break; 2117 2118 case UC_DOUBLE: 2119 d = ucv_double_get(v); 2120 uc_vm_stack_push(vm, ucv_double_new(is_sub ? -d : d)); 2121 break; 2122 2123 case UC_BOOLEAN: 2124 n = (int64_t)ucv_boolean_get(v); 2125 uc_vm_stack_push(vm, ucv_int64_new(is_sub ? -n : n)); 2126 break; 2127 2128 case UC_NULL: 2129 uc_vm_stack_push(vm, ucv_int64_new(0)); 2130 break; 2131 2132 default: 2133 uc_vm_stack_push(vm, ucv_double_new(NAN)); 2134 } 2135 2136 ucv_put(v); 2137 } 2138 2139 static void 2140 uc_vm_insn_bitop(uc_vm_t *vm, uc_vm_insn_t insn) 2141 { 2142 uc_value_t *r2 = uc_vm_stack_pop(vm); 2143 uc_value_t *r1 = uc_vm_stack_pop(vm); 2144 uc_value_t *rv; 2145 2146 rv = uc_vm_value_bitop(vm, insn, r1, r2); 2147 2148 ucv_put(r1); 2149 ucv_put(r2); 2150 2151 uc_vm_stack_push(vm, rv); 2152 } 2153 2154 static void 2155 uc_vm_insn_complement(uc_vm_t *vm, uc_vm_insn_t insn) 2156 { 2157 uc_value_t *v = uc_vm_stack_pop(vm); 2158 uc_value_t *nv; 2159 uint64_t u; 2160 int64_t n; 2161 2162 nv = ucv_to_number(v); 2163 n = int64(nv, &u); 2164 2165 if (n < 0) { 2166 uc_vm_stack_push(vm, ucv_int64_new(~n)); 2167 } 2168 else { 2169 if (!u) u = (uint64_t)n; 2170 2171 uc_vm_stack_push(vm, ucv_uint64_new(~u)); 2172 } 2173 2174 ucv_put(nv); 2175 ucv_put(v); 2176 } 2177 2178 static void 2179 uc_vm_insn_rel(uc_vm_t *vm, uc_vm_insn_t insn) 2180 { 2181 uc_value_t *r2 = uc_vm_stack_pop(vm); 2182 uc_value_t *r1 = uc_vm_stack_pop(vm); 2183 2184 bool res = ucv_compare(insn, r1, r2, NULL); 2185 2186 ucv_put(r1); 2187 ucv_put(r2); 2188 2189 uc_vm_stack_push(vm, ucv_boolean_new(res)); 2190 } 2191 2192 static void 2193 uc_vm_insn_in(uc_vm_t *vm, uc_vm_insn_t insn) 2194 { 2195 uc_value_t *r2 = uc_vm_stack_pop(vm); 2196 uc_value_t *r1 = uc_vm_stack_pop(vm); 2197 uc_value_t *item; 2198 size_t arrlen, arridx; 2199 bool found = false; 2200 2201 switch (ucv_type(r2)) { 2202 case UC_ARRAY: 2203 for (arridx = 0, arrlen = ucv_array_length(r2); 2204 arridx < arrlen; arridx++) { 2205 item = ucv_array_get(r2, arridx); 2206 2207 if (uc_vm_test_strict_equality(r1, item, true)) { 2208 found = true; 2209 break; 2210 } 2211 } 2212 2213 break; 2214 2215 case UC_OBJECT: 2216 if (ucv_type(r1) == UC_STRING) 2217 ucv_object_get(r2, ucv_string_get(r1), &found); 2218 2219 break; 2220 2221 default: 2222 found = false; 2223 } 2224 2225 ucv_put(r1); 2226 ucv_put(r2); 2227 2228 uc_vm_stack_push(vm, ucv_boolean_new(found)); 2229 } 2230 2231 static void 2232 uc_vm_insn_equality(uc_vm_t *vm, uc_vm_insn_t insn) 2233 { 2234 uc_value_t *r2 = uc_vm_stack_pop(vm); 2235 uc_value_t *r1 = uc_vm_stack_pop(vm); 2236 bool equal = uc_vm_test_strict_equality(r1, r2, false); 2237 2238 ucv_put(r1); 2239 ucv_put(r2); 2240 2241 uc_vm_stack_push(vm, ucv_boolean_new((insn == I_EQS) ? equal : !equal)); 2242 } 2243 2244 static void 2245 uc_vm_insn_not(uc_vm_t *vm, uc_vm_insn_t insn) 2246 { 2247 uc_value_t *r1 = uc_vm_stack_pop(vm); 2248 2249 uc_vm_stack_push(vm, ucv_boolean_new(!ucv_is_truish(r1))); 2250 ucv_put(r1); 2251 } 2252 2253 static void 2254 uc_vm_insn_jmp(uc_vm_t *vm, uc_vm_insn_t insn) 2255 { 2256 uc_callframe_t *frame = uc_vm_current_frame(vm); 2257 uc_chunk_t *chunk = uc_vm_frame_chunk(frame); 2258 int32_t addr = vm->arg.s32; 2259 2260 /* ip already has been incremented */ 2261 addr -= 5; 2262 2263 if (frame->ip + addr < chunk->entries || 2264 frame->ip + addr >= chunk->entries + chunk->count) { 2265 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, "jump target out of range"); 2266 return; 2267 } 2268 2269 frame->ip += addr; 2270 } 2271 2272 static void 2273 uc_vm_insn_jmpz(uc_vm_t *vm, uc_vm_insn_t insn) 2274 { 2275 uc_callframe_t *frame = uc_vm_current_frame(vm); 2276 uc_chunk_t *chunk = uc_vm_frame_chunk(frame); 2277 uc_value_t *v = uc_vm_stack_pop(vm); 2278 int32_t addr = vm->arg.s32; 2279 2280 /* ip already has been incremented */ 2281 addr -= 5; 2282 2283 if (frame->ip + addr < chunk->entries || 2284 frame->ip + addr >= chunk->entries + chunk->count) { 2285 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, "jump target out of range"); 2286 return; 2287 } 2288 2289 if (!ucv_is_truish(v)) 2290 frame->ip += addr; 2291 2292 ucv_put(v); 2293 } 2294 2295 static void 2296 uc_vm_insn_jmpnt(uc_vm_t *vm, uc_vm_insn_t insn) 2297 { 2298 uc_callframe_t *frame = uc_vm_current_frame(vm); 2299 uc_chunk_t *chunk = uc_vm_frame_chunk(frame); 2300 int16_t addr = (vm->arg.u32 & 0xffff) - 0x7fff; 2301 uint16_t types = (vm->arg.u32 >> 16) & 0x1fff; 2302 uint8_t depth = (vm->arg.u32 >> 29) & 0x7; 2303 uc_value_t *v = uc_vm_stack_peek(vm, 0); 2304 size_t i; 2305 2306 /* ip already has been incremented */ 2307 addr -= 5; 2308 2309 if (frame->ip + addr < chunk->entries || 2310 frame->ip + addr >= chunk->entries + chunk->count) { 2311 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, "jump target out of range"); 2312 return; 2313 } 2314 2315 if (!(types & (1u << ucv_type(v)))) { 2316 for (i = 0; i <= depth; i++) 2317 ucv_put(uc_vm_stack_pop(vm)); 2318 2319 uc_vm_stack_push(vm, NULL); 2320 frame->ip += addr; 2321 } 2322 } 2323 2324 2325 static void 2326 uc_vm_object_iterator_free(void *ud) 2327 { 2328 uc_object_iterator_t *iter = ud; 2329 2330 uc_list_remove(&iter->list); 2331 } 2332 2333 static uc_resource_type_t uc_vm_object_iterator_type = { 2334 .name = "object iterator", 2335 .free = uc_vm_object_iterator_free 2336 }; 2337 2338 static bool 2339 uc_vm_object_iterator_next(uc_vm_t *vm, uc_vm_insn_t insn, 2340 uc_value_t *k, uc_value_t *v) 2341 { 2342 uc_resource_t *res = (uc_resource_t *)k; 2343 uc_object_t *obj = (uc_object_t *)v; 2344 uc_object_iterator_t *iter; 2345 2346 if (!res) { 2347 /* object is empty */ 2348 if (!obj->table->head) 2349 return false; 2350 2351 res = xalloc(sizeof(*res) + sizeof(uc_object_iterator_t)); 2352 res->header.type = UC_RESOURCE; 2353 res->header.refcount = 1; 2354 res->type = &uc_vm_object_iterator_type; 2355 2356 iter = res->data = (char *)res + sizeof(*res); 2357 iter->table = obj->table; 2358 iter->u.pos = obj->table->head; 2359 2360 uc_list_insert(&uc_thread_context_get()->object_iterators, &iter->list); 2361 } 2362 else if (ucv_type(k) == UC_RESOURCE && 2363 res->type == &uc_vm_object_iterator_type && res->data != NULL) { 2364 2365 iter = res->data; 2366 } 2367 else { 2368 uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Invalid object iterator"); 2369 2370 return false; 2371 } 2372 2373 /* no next key */ 2374 if (!iter->u.pos) { 2375 uc_list_remove(&iter->list); 2376 2377 return false; 2378 } 2379 2380 uc_vm_stack_push(vm, ucv_string_new(iter->u.pos->k)); 2381 2382 if (insn == I_NEXTKV) 2383 uc_vm_stack_push(vm, ucv_get((uc_value_t *)iter->u.pos->v)); 2384 2385 uc_vm_stack_push(vm, &res->header); 2386 ucv_put(v); 2387 2388 iter->u.pos = iter->u.pos->next; 2389 2390 return true; 2391 } 2392 2393 static bool 2394 uc_vm_array_iterator_next(uc_vm_t *vm, uc_vm_insn_t insn, 2395 uc_value_t *k, uc_value_t *v) 2396 { 2397 uint64_t n; 2398 2399 if (!k) { 2400 /* array is empty */ 2401 if (!ucv_array_length(v)) 2402 return false; 2403 2404 k = ucv_resource_new(NULL, NULL); 2405 n = 0; 2406 } 2407 else if (ucv_type(k) == UC_RESOURCE) { 2408 n = (uintptr_t)ucv_resource_data(k, NULL); 2409 } 2410 else { 2411 uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Invalid array iterator"); 2412 2413 return false; 2414 } 2415 2416 /* no next index */ 2417 if (n >= ucv_array_length(v)) 2418 return false; 2419 2420 if (insn == I_NEXTKV) 2421 uc_vm_stack_push(vm, ucv_uint64_new(n)); 2422 2423 uc_vm_stack_push(vm, ucv_get(ucv_array_get(v, n))); 2424 2425 uc_vm_stack_push(vm, k); 2426 ucv_put(v); 2427 2428 ((uc_resource_t *)k)->data = (void *)(uintptr_t)(n + 1); 2429 2430 return true; 2431 } 2432 2433 static void 2434 uc_vm_insn_next(uc_vm_t *vm, uc_vm_insn_t insn) 2435 { 2436 uc_value_t *k = uc_vm_stack_pop(vm); 2437 uc_value_t *v = uc_vm_stack_pop(vm); 2438 2439 switch (ucv_type(v)) { 2440 case UC_OBJECT: 2441 if (uc_vm_object_iterator_next(vm, insn, k, v)) 2442 return; 2443 2444 break; 2445 2446 case UC_ARRAY: 2447 if (uc_vm_array_iterator_next(vm, insn, k, v)) 2448 return; 2449 2450 break; 2451 2452 default: 2453 break; 2454 } 2455 2456 uc_vm_stack_push(vm, NULL); 2457 uc_vm_stack_push(vm, NULL); 2458 2459 if (insn == I_NEXTKV) 2460 uc_vm_stack_push(vm, NULL); 2461 2462 ucv_put(k); 2463 ucv_put(v); 2464 } 2465 2466 static void 2467 uc_vm_insn_close_upval(uc_vm_t *vm, uc_vm_insn_t insn) 2468 { 2469 uc_vm_close_upvals(vm, vm->stack.count - 1); 2470 ucv_put(uc_vm_stack_pop(vm)); 2471 } 2472 2473 static void 2474 uc_vm_insn_call(uc_vm_t *vm, uc_vm_insn_t insn) 2475 { 2476 bool mcall = (vm->arg.u32 & 0x80000000); 2477 size_t nargs = (vm->arg.u32 & 0xffff); 2478 uc_value_t *fno = uc_vm_stack_peek(vm, nargs); 2479 uc_value_t *ctx = NULL; 2480 2481 if (!ucv_is_arrowfn(fno)) 2482 ctx = mcall ? uc_vm_stack_peek(vm, nargs + 1) : NULL; 2483 else if (vm->callframes.count > 0) 2484 ctx = uc_vm_current_frame(vm)->ctx; 2485 2486 uc_vm_call_function(vm, ucv_get(ctx), ucv_get(fno), mcall, vm->arg.u32); 2487 } 2488 2489 static void 2490 uc_vm_insn_print(uc_vm_t *vm, uc_vm_insn_t insn) 2491 { 2492 uc_value_t *v = uc_vm_stack_pop(vm); 2493 char *p; 2494 2495 switch (ucv_type(v)) { 2496 case UC_OBJECT: 2497 case UC_ARRAY: 2498 p = ucv_to_jsonstring(vm, v); 2499 fwrite(p, 1, strlen(p), vm->output); 2500 free(p); 2501 break; 2502 2503 case UC_STRING: 2504 fwrite(ucv_string_get(v), 1, ucv_string_length(v), vm->output); 2505 break; 2506 2507 case UC_NULL: 2508 break; 2509 2510 default: 2511 p = ucv_to_string(vm, v); 2512 fwrite(p, 1, strlen(p), vm->output); 2513 free(p); 2514 } 2515 2516 ucv_put(v); 2517 } 2518 2519 static void 2520 uc_vm_insn_delete(uc_vm_t *vm, uc_vm_insn_t insn) 2521 { 2522 uc_value_t *k = uc_vm_stack_pop(vm); 2523 uc_value_t *v = uc_vm_stack_pop(vm); 2524 bool rv; 2525 2526 switch (ucv_type(v)) { 2527 case UC_OBJECT: 2528 if (assert_mutable_value(vm, v)) { 2529 rv = ucv_key_delete(vm, v, k); 2530 uc_vm_stack_push(vm, ucv_boolean_new(rv)); 2531 } 2532 2533 break; 2534 2535 default: 2536 uc_vm_raise_exception(vm, EXCEPTION_REFERENCE, 2537 "left-hand side expression is %s", 2538 v ? "not an object" : "null"); 2539 2540 break; 2541 } 2542 2543 ucv_put(k); 2544 ucv_put(v); 2545 } 2546 2547 static void 2548 uc_vm_insn_import(uc_vm_t *vm, uc_vm_insn_t insn) 2549 { 2550 uc_callframe_t *frame = uc_vm_current_frame(vm); 2551 uc_program_t *prog = uc_vm_current_program(vm); 2552 uint16_t from = vm->arg.u32 & 0xffff; 2553 uint16_t to = vm->arg.u32 >> 16; 2554 uc_value_t *name, *modobj; 2555 uint32_t cidx; 2556 2557 /* is a wildcard import * from ... */ 2558 if (to == 0xffff) { 2559 to = from; 2560 modobj = ucv_object_new(vm); 2561 2562 /* instruction is followed by u16 containing the offset of the 2563 * first module export and `from` times u32 values containing 2564 * the constant indexes of the names */ 2565 for (from = frame->ip[0] * 0x100 + frame->ip[1], frame->ip += 2; 2566 from < prog->exports.count && to > 0; 2567 from++, to--) { 2568 2569 cidx = ( 2570 frame->ip[0] * 0x1000000UL + 2571 frame->ip[1] * 0x10000UL + 2572 frame->ip[2] * 0x100UL + 2573 frame->ip[3] 2574 ); 2575 2576 frame->ip += 4; 2577 2578 name = uc_program_get_constant(uc_vm_current_program(vm), cidx); 2579 2580 if (ucv_type(name) == UC_STRING && prog->exports.entries[from]) 2581 ucv_object_add(modobj, ucv_string_get(name), 2582 ucv_get(&prog->exports.entries[from]->header)); 2583 2584 ucv_put(name); 2585 } 2586 2587 ucv_set_constant(modobj, true); 2588 2589 uc_vm_stack_push(vm, modobj); 2590 } 2591 2592 /* module export available, patch into upvalue */ 2593 else if (from <= prog->exports.count && prog->exports.entries[from]) { 2594 frame->closure->upvals[to] = prog->exports.entries[from]; 2595 ucv_get(&prog->exports.entries[from]->header); 2596 } 2597 2598 /* module export missing, e.g. due to premature return in module, 2599 * patch up dummy upvalue ref with `null` value */ 2600 else { 2601 frame->closure->upvals[to] = (uc_upvalref_t *)ucv_upvalref_new(0); 2602 frame->closure->upvals[to]->closed = true; 2603 } 2604 } 2605 2606 static void 2607 uc_vm_insn_export(uc_vm_t *vm, uc_vm_insn_t insn) 2608 { 2609 uc_callframe_t *frame = uc_vm_current_frame(vm); 2610 uc_program_t *prog = uc_vm_current_program(vm); 2611 uc_upvalref_t *ref = uc_vm_capture_upval(vm, frame->stackframe + vm->arg.u32); 2612 2613 uc_vector_push(&prog->exports, ref); 2614 ucv_get(&ref->header); 2615 } 2616 2617 static void 2618 uc_vm_insn_dynload(uc_vm_t *vm, uc_vm_insn_t insn) 2619 { 2620 uc_callframe_t *frame = uc_vm_current_frame(vm); 2621 uc_value_t *name, *export, *modscope, *modobj; 2622 uint16_t count = vm->arg.u32 & 0xffff; 2623 uint16_t to = vm->arg.u32 >> 16; 2624 uint32_t cidx; 2625 bool found; 2626 2627 /* Attempt to load module. Will raise exception on error */ 2628 name = uc_vm_stack_pop(vm); 2629 modscope = uc_require_library(vm, name, true); 2630 ucv_put(name); 2631 2632 if (!modscope) 2633 return; 2634 2635 /* If count is zero, we're doing a wildcard import. Shallow copy module 2636 * object, mark it constant and patch into the target upvalue. */ 2637 if (count == 0) { 2638 modobj = ucv_object_new(vm); 2639 2640 ucv_object_foreach(modscope, k, v) 2641 ucv_object_add(modobj, k, ucv_get(v)); 2642 2643 ucv_set_constant(modobj, true); 2644 2645 uc_vm_stack_push(vm, modobj); 2646 } 2647 2648 /* ... otherwise we're importing a specific list of names */ 2649 else { 2650 /* Instruction is followed by `count` times u32 values containing 2651 * the import name constant indexes */ 2652 while (count > 0) { 2653 cidx = ( 2654 frame->ip[0] * 0x1000000UL + 2655 frame->ip[1] * 0x10000UL + 2656 frame->ip[2] * 0x100UL + 2657 frame->ip[3] 2658 ); 2659 2660 frame->ip += 4; 2661 2662 name = uc_program_get_constant(uc_vm_current_program(vm), cidx); 2663 export = ucv_object_get(modscope, ucv_string_get(name), &found); 2664 2665 if (!found) { 2666 uc_vm_raise_exception(vm, EXCEPTION_REFERENCE, 2667 "Module does not export %s", 2668 ucv_string_get(name)); 2669 2670 ucv_put(name); 2671 2672 return; 2673 } 2674 2675 ucv_put(name); 2676 2677 frame->closure->upvals[to] = (uc_upvalref_t *)ucv_upvalref_new(0); 2678 frame->closure->upvals[to]->closed = true; 2679 frame->closure->upvals[to]->value = ucv_get(export); 2680 2681 count--; 2682 to++; 2683 } 2684 } 2685 } 2686 2687 static void 2688 uc_vm_gc_step(uc_vm_t *vm) 2689 { 2690 size_t curr_count = 0, prev_count = 0; 2691 uc_weakref_t *ref; 2692 2693 if (!(vm->gc_flags & GC_ENABLED)) 2694 return; 2695 2696 if (vm->alloc_refs >= vm->gc_interval) { 2697 if (vm->trace) { 2698 for (ref = vm->values.next; ref != &vm->values; ref = ref->next) 2699 prev_count++; 2700 2701 ucv_gc(vm); 2702 2703 for (ref = vm->values.next; ref != &vm->values; ref = ref->next) 2704 curr_count++; 2705 2706 fprintf(stderr, "! GC reclaimed %zu object(s)\n", prev_count - curr_count); 2707 } 2708 else { 2709 ucv_gc(vm); 2710 } 2711 } 2712 } 2713 2714 static uc_value_t * 2715 uc_vm_callframe_pop(uc_vm_t *vm) 2716 { 2717 uc_callframe_t *frame = uc_vm_current_frame(vm); 2718 uc_value_t *retval; 2719 2720 /* close upvalues */ 2721 uc_vm_close_upvals(vm, frame->stackframe); 2722 2723 if (vm->stack.count > frame->stackframe) 2724 retval = uc_vm_stack_pop(vm); 2725 else 2726 retval = NULL; 2727 2728 /* reset function stack frame */ 2729 while (vm->stack.count > frame->stackframe) 2730 ucv_put(uc_vm_stack_pop(vm)); 2731 2732 /* for method calls, release context as well */ 2733 if (frame->mcall) 2734 ucv_put(uc_vm_stack_pop(vm)); 2735 2736 /* release function */ 2737 if (frame->closure) 2738 ucv_put(&frame->closure->header); 2739 2740 if (frame->cfunction) 2741 ucv_put(&frame->cfunction->header); 2742 2743 /* release context */ 2744 ucv_put(frame->ctx); 2745 2746 vm->callframes.count--; 2747 2748 return retval; 2749 } 2750 2751 static void 2752 uc_vm_output_exception(uc_vm_t *vm, uc_exception_t *ex) 2753 { 2754 uc_value_t *ctx; 2755 2756 if (ex->type == EXCEPTION_USER) 2757 fprintf(stderr, "%s\n", ex->message); 2758 else 2759 fprintf(stderr, "%s: %s\n", 2760 exception_type_strings[ex->type] ? exception_type_strings[ex->type] : "Error", 2761 ex->message); 2762 2763 ctx = ucv_object_get(ucv_array_get(ex->stacktrace, 0), "context", NULL); 2764 2765 if (ctx) 2766 fprintf(stderr, "%s\n", ucv_string_get(ctx)); 2767 2768 fprintf(stderr, "\n"); 2769 } 2770 2771 uc_exception_type_t 2772 uc_vm_signal_dispatch(uc_vm_t *vm) 2773 { 2774 uc_exception_type_t ex; 2775 uc_value_t *handler; 2776 uint64_t mask; 2777 size_t i, j; 2778 int sig, rv; 2779 2780 if (!vm->config->setup_signal_handlers) 2781 return EXCEPTION_NONE; 2782 2783 for (i = 0; i < ARRAY_SIZE(vm->signal.raised); i++) { 2784 if (!vm->signal.raised[i]) 2785 continue; 2786 2787 do { 2788 rv = read(vm->signal.sigpipe[0], &sig, sizeof(sig)); 2789 } while (rv > 0 || (rv == -1 && errno == EINTR)); 2790 2791 for (j = 0; j < 64; j++) { 2792 mask = 1ull << j; 2793 2794 if (vm->signal.raised[i] & mask) { 2795 vm->signal.raised[i] &= ~mask; 2796 2797 sig = i * 64 + j; 2798 handler = ucv_array_get(vm->signal.handler, sig); 2799 2800 if (ucv_is_callable(handler)) { 2801 uc_vm_stack_push(vm, ucv_get(handler)); 2802 uc_vm_stack_push(vm, ucv_int64_new(sig)); 2803 2804 ex = uc_vm_call(vm, false, 1); 2805 2806 if (ex != EXCEPTION_NONE) 2807 return ex; 2808 2809 ucv_put(uc_vm_stack_pop(vm)); 2810 } 2811 } 2812 } 2813 } 2814 2815 return EXCEPTION_NONE; 2816 } 2817 2818 static uc_vm_status_t 2819 uc_vm_execute_chunk(uc_vm_t *vm) 2820 { 2821 uc_callframe_t *frame = NULL; 2822 uc_chunk_t *chunk = NULL; 2823 size_t caller = vm->callframes.count - 1; 2824 uc_value_t *retval; 2825 uc_vm_insn_t insn; 2826 uint8_t *ip; 2827 2828 while (vm->callframes.count > caller) { 2829 frame = &vm->callframes.entries[vm->callframes.count - 1]; 2830 chunk = uc_vm_frame_chunk(frame); 2831 2832 if (!chunk) 2833 break; 2834 2835 if (vm->trace) { 2836 ip = frame->ip; 2837 insn = uc_vm_decode_insn(vm, frame, chunk); 2838 uc_dump_insn(vm, ip, insn); 2839 } 2840 else { 2841 insn = uc_vm_decode_insn(vm, frame, chunk); 2842 } 2843 2844 switch (insn) { 2845 case I_LOAD: 2846 case I_LOAD8: 2847 case I_LOAD16: 2848 case I_LOAD32: 2849 uc_vm_insn_load(vm, insn); 2850 break; 2851 2852 case I_LREXP: 2853 uc_vm_insn_load_regexp(vm, insn); 2854 break; 2855 2856 case I_LNULL: 2857 uc_vm_insn_load_null(vm, insn); 2858 break; 2859 2860 case I_LTRUE: 2861 case I_LFALSE: 2862 uc_vm_insn_load_bool(vm, insn); 2863 break; 2864 2865 case I_LTHIS: 2866 uc_vm_stack_push(vm, ucv_get(frame->ctx)); 2867 break; 2868 2869 case I_LVAR: 2870 uc_vm_insn_load_var(vm, insn); 2871 break; 2872 2873 case I_LVAL: 2874 uc_vm_insn_load_val(vm, insn); 2875 break; 2876 2877 case I_PVAL: 2878 uc_vm_insn_peek_val(vm, insn); 2879 break; 2880 2881 case I_LUPV: 2882 uc_vm_insn_load_upval(vm, insn); 2883 break; 2884 2885 case I_LLOC: 2886 uc_vm_insn_load_local(vm, insn); 2887 break; 2888 2889 case I_CLFN: 2890 case I_ARFN: 2891 uc_vm_insn_load_closure(vm, insn); 2892 break; 2893 2894 case I_NARR: 2895 uc_vm_insn_narr(vm, insn); 2896 break; 2897 2898 case I_PARR: 2899 uc_vm_insn_parr(vm, insn); 2900 break; 2901 2902 case I_MARR: 2903 uc_vm_insn_marr(vm, insn); 2904 break; 2905 2906 case I_NOBJ: 2907 uc_vm_insn_nobj(vm, insn); 2908 break; 2909 2910 case I_SOBJ: 2911 uc_vm_insn_sobj(vm, insn); 2912 break; 2913 2914 case I_MOBJ: 2915 uc_vm_insn_mobj(vm, insn); 2916 break; 2917 2918 case I_SVAR: 2919 uc_vm_insn_store_var(vm, insn); 2920 break; 2921 2922 case I_SVAL: 2923 uc_vm_insn_store_val(vm, insn); 2924 break; 2925 2926 case I_SUPV: 2927 uc_vm_insn_store_upval(vm, insn); 2928 break; 2929 2930 case I_SLOC: 2931 uc_vm_insn_store_local(vm, insn); 2932 break; 2933 2934 case I_UVAR: 2935 uc_vm_insn_update_var(vm, insn); 2936 break; 2937 2938 case I_UVAL: 2939 uc_vm_insn_update_val(vm, insn); 2940 break; 2941 2942 case I_UUPV: 2943 uc_vm_insn_update_upval(vm, insn); 2944 break; 2945 2946 case I_ULOC: 2947 uc_vm_insn_update_local(vm, insn); 2948 break; 2949 2950 case I_ADD: 2951 case I_SUB: 2952 case I_MUL: 2953 case I_DIV: 2954 case I_MOD: 2955 case I_EXP: 2956 uc_vm_insn_arith(vm, insn); 2957 break; 2958 2959 case I_PLUS: 2960 case I_MINUS: 2961 uc_vm_insn_plus_minus(vm, insn); 2962 break; 2963 2964 case I_LSHIFT: 2965 case I_RSHIFT: 2966 case I_BAND: 2967 case I_BXOR: 2968 case I_BOR: 2969 uc_vm_insn_bitop(vm, insn); 2970 break; 2971 2972 case I_COMPL: 2973 uc_vm_insn_complement(vm, insn); 2974 break; 2975 2976 case I_EQS: 2977 case I_NES: 2978 uc_vm_insn_equality(vm, insn); 2979 break; 2980 2981 case I_EQ: 2982 case I_NE: 2983 case I_LT: 2984 case I_LE: 2985 case I_GT: 2986 case I_GE: 2987 uc_vm_insn_rel(vm, insn); 2988 break; 2989 2990 case I_IN: 2991 uc_vm_insn_in(vm, insn); 2992 break; 2993 2994 case I_NOT: 2995 uc_vm_insn_not(vm, insn); 2996 break; 2997 2998 case I_JMP: 2999 uc_vm_insn_jmp(vm, insn); 3000 break; 3001 3002 case I_JMPZ: 3003 uc_vm_insn_jmpz(vm, insn); 3004 break; 3005 3006 case I_JMPNT: 3007 uc_vm_insn_jmpnt(vm, insn); 3008 break; 3009 3010 case I_NEXTK: 3011 case I_NEXTKV: 3012 uc_vm_insn_next(vm, insn); 3013 break; 3014 3015 case I_COPY: 3016 uc_vm_stack_push(vm, ucv_get(uc_vm_stack_peek(vm, vm->arg.u8))); 3017 break; 3018 3019 case I_POP: 3020 ucv_put(uc_vm_stack_pop(vm)); 3021 uc_vm_gc_step(vm); 3022 break; 3023 3024 case I_CUPV: 3025 uc_vm_insn_close_upval(vm, insn); 3026 break; 3027 3028 case I_CALL: 3029 uc_vm_insn_call(vm, insn); 3030 break; 3031 3032 case I_RETURN: 3033 retval = uc_vm_callframe_pop(vm); 3034 3035 uc_vm_stack_push(vm, retval); 3036 3037 if (vm->callframes.count == 0) 3038 return STATUS_OK; 3039 break; 3040 3041 case I_PRINT: 3042 uc_vm_insn_print(vm, insn); 3043 break; 3044 3045 case I_DELETE: 3046 uc_vm_insn_delete(vm, insn); 3047 break; 3048 3049 case I_IMPORT: 3050 uc_vm_insn_import(vm, insn); 3051 break; 3052 3053 case I_EXPORT: 3054 uc_vm_insn_export(vm, insn); 3055 break; 3056 3057 case I_DYNLOAD: 3058 uc_vm_insn_dynload(vm, insn); 3059 break; 3060 3061 default: 3062 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, "unknown opcode %d", insn); 3063 break; 3064 } 3065 3066 exception: 3067 /* previous instruction raised exception */ 3068 if (vm->exception.type != EXCEPTION_NONE) { 3069 /* VM termination was requested */ 3070 if (vm->exception.type == EXCEPTION_EXIT) { 3071 uc_vm_reset_callframes(vm); 3072 3073 return STATUS_EXIT; 3074 } 3075 3076 /* walk up callframes until something handles the exception or the original caller is reached */ 3077 while (!uc_vm_handle_exception(vm)) { 3078 /* no further callframe, report unhandled exception and terminate */ 3079 if (vm->callframes.count == 0) 3080 return ERROR_RUNTIME; 3081 3082 /* if VM returned into native function, don't bubble up */ 3083 if (!vm->callframes.entries[vm->callframes.count - 1].closure) 3084 return ERROR_RUNTIME; 3085 3086 /* no exception handler in current function, pop callframe */ 3087 ucv_put(uc_vm_callframe_pop(vm)); 3088 3089 /* do not bubble past original call depth */ 3090 if (vm->callframes.count <= caller) 3091 return ERROR_RUNTIME; 3092 } 3093 } 3094 3095 /* run handler for signal(s) delivered during previous instruction */ 3096 if (uc_vm_signal_dispatch(vm) != EXCEPTION_NONE) 3097 goto exception; 3098 } 3099 3100 return STATUS_OK; 3101 } 3102 3103 uc_vm_status_t 3104 uc_vm_execute(uc_vm_t *vm, uc_program_t *program, uc_value_t **retval) 3105 { 3106 uc_function_t *fn = uc_program_entry(program); 3107 uc_closure_t *closure = (uc_closure_t *)ucv_closure_new(vm, fn, false); 3108 uc_vm_status_t status; 3109 uc_callframe_t *frame; 3110 uc_stringbuf_t *buf; 3111 uc_value_t *val; 3112 3113 frame = uc_vector_push(&vm->callframes, { 3114 .closure = closure, 3115 .stackframe = 0, 3116 .ip = closure->function->chunk.entries, 3117 .strict = fn->strict 3118 }); 3119 3120 if (vm->trace) { 3121 buf = xprintbuf_new(); 3122 3123 uc_source_context_format(buf, uc_vm_frame_source(frame), 0, true); 3124 3125 fwrite(buf->buf, 1, printbuf_length(buf), stderr); 3126 printbuf_free(buf); 3127 3128 uc_vm_frame_dump(vm, frame); 3129 } 3130 3131 //uc_vm_stack_push(vm, closure->header.jso); 3132 uc_vm_stack_push(vm, NULL); 3133 3134 status = uc_vm_execute_chunk(vm); 3135 3136 switch (status) { 3137 case STATUS_OK: 3138 val = uc_vm_stack_pop(vm); 3139 3140 if (retval) 3141 *retval = val; 3142 else 3143 ucv_put(val); 3144 3145 break; 3146 3147 case STATUS_EXIT: 3148 if (retval) 3149 *retval = ucv_int64_new(vm->arg.s32); 3150 3151 break; 3152 3153 default: 3154 if (vm->exhandler) 3155 vm->exhandler(vm, &vm->exception); 3156 3157 if (retval) 3158 *retval = NULL; 3159 3160 break; 3161 } 3162 3163 return status; 3164 } 3165 3166 uc_exception_type_t 3167 uc_vm_call(uc_vm_t *vm, bool mcall, size_t nargs) 3168 { 3169 uc_value_t *ctx = mcall ? ucv_get(uc_vm_stack_peek(vm, nargs + 1)) : NULL; 3170 uc_value_t *fno = ucv_get(uc_vm_stack_peek(vm, nargs)); 3171 3172 uc_vm_clear_exception(vm); 3173 3174 if (uc_vm_call_function(vm, ctx, fno, mcall, nargs & 0xffff)) { 3175 if (ucv_type(fno) != UC_CFUNCTION) 3176 uc_vm_execute_chunk(vm); 3177 } 3178 3179 return vm->exception.type; 3180 } 3181 3182 uc_value_t * 3183 uc_vm_scope_get(uc_vm_t *vm) 3184 { 3185 return vm->globals; 3186 } 3187 3188 void 3189 uc_vm_scope_set(uc_vm_t *vm, uc_value_t *ctx) 3190 { 3191 ucv_put(vm->globals); 3192 vm->globals = ctx; 3193 } 3194 3195 uc_value_t * 3196 uc_vm_invoke(uc_vm_t *vm, const char *fname, size_t nargs, ...) 3197 { 3198 uc_exception_type_t ex; 3199 uc_value_t *fno, *arg; 3200 va_list ap; 3201 size_t i; 3202 3203 fno = ucv_property_get(vm->globals, fname); 3204 3205 if (!ucv_is_callable(fno)) 3206 return NULL; 3207 3208 uc_vm_stack_push(vm, ucv_get(fno)); 3209 3210 va_start(ap, nargs); 3211 3212 for (i = 0; i < nargs; i++) { 3213 arg = va_arg(ap, uc_value_t *); 3214 uc_vm_stack_push(vm, ucv_get(arg)); 3215 } 3216 3217 va_end(ap); 3218 3219 ex = uc_vm_call(vm, false, nargs); 3220 3221 if (ex) { 3222 if (vm->exhandler) 3223 vm->exhandler(vm, &vm->exception); 3224 3225 return NULL; 3226 } 3227 3228 return uc_vm_stack_pop(vm); 3229 } 3230 3231 uc_exception_handler_t * 3232 uc_vm_exception_handler_get(uc_vm_t *vm) 3233 { 3234 return vm->exhandler; 3235 } 3236 3237 void 3238 uc_vm_exception_handler_set(uc_vm_t *vm, uc_exception_handler_t *exhandler) 3239 { 3240 vm->exhandler = exhandler; 3241 } 3242 3243 uint32_t 3244 uc_vm_trace_get(uc_vm_t *vm) 3245 { 3246 return vm->trace; 3247 } 3248 3249 void 3250 uc_vm_trace_set(uc_vm_t *vm, uint32_t level) 3251 { 3252 vm->trace = level; 3253 } 3254 3255 bool 3256 uc_vm_registry_exists(uc_vm_t *vm, const char *key) 3257 { 3258 bool exists; 3259 3260 ucv_object_get(vm->registry, key, &exists); 3261 3262 return exists; 3263 } 3264 3265 uc_value_t * 3266 uc_vm_registry_get(uc_vm_t *vm, const char *key) 3267 { 3268 return ucv_object_get(vm->registry, key, NULL); 3269 } 3270 3271 void 3272 uc_vm_registry_set(uc_vm_t *vm, const char *key, uc_value_t *value) 3273 { 3274 if (!vm->registry) 3275 vm->registry = ucv_object_new(vm); 3276 3277 ucv_object_add(vm->registry, key, value); 3278 } 3279 3280 bool 3281 uc_vm_registry_delete(uc_vm_t *vm, const char *key) 3282 { 3283 return ucv_object_delete(vm->registry, key); 3284 } 3285 3286 bool 3287 uc_vm_gc_start(uc_vm_t *vm, uint16_t interval) 3288 { 3289 bool changed = false; 3290 3291 if (vm->gc_interval != interval) { 3292 vm->gc_interval = interval; 3293 changed = true; 3294 } 3295 3296 if (!(vm->gc_flags & GC_ENABLED)) { 3297 vm->gc_flags |= GC_ENABLED; 3298 changed = true; 3299 } 3300 3301 return changed; 3302 } 3303 3304 bool 3305 uc_vm_gc_stop(uc_vm_t *vm) 3306 { 3307 if (!(vm->gc_flags & GC_ENABLED)) 3308 return false; 3309 3310 vm->gc_flags &= ~GC_ENABLED; 3311 3312 return true; 3313 } 3314 3315 void 3316 uc_vm_signal_raise(uc_vm_t *vm, int signo) 3317 { 3318 uint8_t signum = signo; 3319 3320 if (signo <= 0 || signo >= UC_SYSTEM_SIGNAL_COUNT) 3321 return; 3322 3323 vm->signal.raised[signo / 64] |= (1ull << (signo % 64)); 3324 3325 if (write(vm->signal.sigpipe[1], &signum, sizeof(signum)) == -1) {} 3326 } 3327 3328 int 3329 uc_vm_signal_notifyfd(uc_vm_t *vm) 3330 { 3331 return vm->signal.sigpipe[0]; 3332 } 3333
This page was automatically generated by LXR 0.3.1. • OpenWrt