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