1 /* 2 * Binary data packing/unpacking module for ucode. 3 * Copyright (C) 2021 Jo-Philipp Wich <jo@mein.io> 4 * 5 * This module is heavily based on the Python 3.10 "_struct.c" module source 6 * published under the following license: 7 * 8 * ----------------------------------------------------------------------------------- 9 * 10 * 1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and 11 * the Individual or Organization ("Licensee") accessing and otherwise using Python 12 * 3.10.0 software in source or binary form and its associated documentation. 13 * 14 * 2. Subject to the terms and conditions of this License Agreement, PSF hereby 15 * grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, 16 * analyze, test, perform and/or display publicly, prepare derivative works, 17 * distribute, and otherwise use Python 3.10.0 alone or in any derivative 18 * version, provided, however, that PSF's License Agreement and PSF's notice of 19 * copyright, i.e., "Copyright © 2001-2021 Python Software Foundation; All Rights 20 * Reserved" are retained in Python 3.10.0 alone or in any derivative version 21 * prepared by Licensee. 22 * 23 * 3. In the event Licensee prepares a derivative work that is based on or 24 * incorporates Python 3.10.0 or any part thereof, and wants to make the 25 * derivative work available to others as provided herein, then Licensee hereby 26 * agrees to include in any such work a brief summary of the changes made to Python 27 * 3.10.0. 28 * 29 * 4. PSF is making Python 3.10.0 available to Licensee on an "AS IS" basis. 30 * PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF 31 * EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR 32 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE 33 * USE OF PYTHON 3.10.0 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. 34 * 35 * 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 3.10.0 36 * FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF 37 * MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 3.10.0, OR ANY DERIVATIVE 38 * THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. 39 * 40 * 6. This License Agreement will automatically terminate upon a material breach of 41 * its terms and conditions. 42 * 43 * 7. Nothing in this License Agreement shall be deemed to create any relationship 44 * of agency, partnership, or joint venture between PSF and Licensee. This License 45 * Agreement does not grant permission to use PSF trademarks or trade name in a 46 * trademark sense to endorse or promote products or services of Licensee, or any 47 * third party. 48 * 49 * 8. By copying, installing or otherwise using Python 3.10.0, Licensee agrees 50 * to be bound by the terms and conditions of this License Agreement. 51 * 52 * ----------------------------------------------------------------------------------- 53 * 54 * Brief summary of changes compared to the original Python 3.10 source: 55 * 56 * - Inlined and refactored IEEE 754 float conversion routines 57 * - Usage of stdbool for function return values and boolean parameters 58 * - Renamed functions and structures for clarity 59 * - Interface adapated to ucode C api 60 * - Removed unused code 61 */ 62 63 #include <ctype.h> 64 #include <errno.h> 65 #include <limits.h> 66 #include <math.h> 67 #include <stdlib.h> 68 #include <float.h> 69 #include <assert.h> 70 71 #include "ucode/module.h" 72 #include "ucode/vallist.h" 73 74 static uc_resource_type_t *struct_type; 75 76 typedef struct formatdef { 77 char format; 78 ssize_t size; 79 ssize_t alignment; 80 uc_value_t* (*unpack)(uc_vm_t *, const char *, const struct formatdef *); 81 bool (*pack)(uc_vm_t *, char *, uc_value_t *, const struct formatdef *); 82 } formatdef_t; 83 84 typedef struct { 85 const formatdef_t *fmtdef; 86 ssize_t offset; 87 ssize_t size; 88 ssize_t repeat; 89 } formatcode_t; 90 91 typedef struct { 92 size_t len; 93 size_t size; 94 size_t ncodes; 95 formatcode_t codes[]; 96 } formatstate_t; 97 98 99 /* Define various structs to figure out the alignments of types */ 100 101 typedef struct { char c; short x; } st_short; 102 typedef struct { char c; int x; } st_int; 103 typedef struct { char c; long x; } st_long; 104 typedef struct { char c; float x; } st_float; 105 typedef struct { char c; double x; } st_double; 106 typedef struct { char c; void *x; } st_void_p; 107 typedef struct { char c; size_t x; } st_size_t; 108 typedef struct { char c; bool x; } st_bool; 109 typedef struct { char c; long long x; } s_long_long; 110 111 #define SHORT_ALIGN (sizeof(st_short) - sizeof(short)) 112 #define INT_ALIGN (sizeof(st_int) - sizeof(int)) 113 #define LONG_ALIGN (sizeof(st_long) - sizeof(long)) 114 #define FLOAT_ALIGN (sizeof(st_float) - sizeof(float)) 115 #define DOUBLE_ALIGN (sizeof(st_double) - sizeof(double)) 116 #define VOID_P_ALIGN (sizeof(st_void_p) - sizeof(void *)) 117 #define SIZE_T_ALIGN (sizeof(st_size_t) - sizeof(size_t)) 118 #define BOOL_ALIGN (sizeof(st_bool) - sizeof(bool)) 119 #define LONG_LONG_ALIGN (sizeof(s_long_long) - sizeof(long long)) 120 121 #ifdef __powerc 122 #pragma options align=reset 123 #endif 124 125 126 static bool 127 ucv_as_long(uc_vm_t *vm, uc_value_t *v, long *p) 128 { 129 char *s, *e; 130 int64_t i; 131 double d; 132 long x; 133 134 errno = 0; 135 136 switch (ucv_type(v)) { 137 case UC_INTEGER: 138 i = ucv_int64_get(v); 139 140 if (i < LONG_MIN || i > LONG_MAX) 141 errno = ERANGE; 142 143 x = (long)i; 144 break; 145 146 case UC_DOUBLE: 147 d = ucv_double_get(v); 148 x = (long)d; 149 150 if (isnan(d) || d < (double)LONG_MIN || d > (double)LONG_MAX || d - x != 0) 151 errno = ERANGE; 152 153 break; 154 155 case UC_BOOLEAN: 156 x = (long)ucv_boolean_get(v); 157 break; 158 159 case UC_NULL: 160 x = 0; 161 break; 162 163 case UC_STRING: 164 s = ucv_string_get(v); 165 x = strtol(s, &e, 0); 166 167 if (e == s || *e != '\0') 168 errno = EINVAL; 169 170 break; 171 172 default: 173 errno = EINVAL; 174 x = 0; 175 break; 176 } 177 178 if (errno != 0) { 179 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 180 (errno == ERANGE) 181 ? "Argument out of range" 182 : "Argument not convertible to number"); 183 184 return false; 185 } 186 187 *p = x; 188 189 return true; 190 } 191 192 static bool 193 ucv_as_ulong(uc_vm_t *vm, uc_value_t *v, unsigned long *p) 194 { 195 unsigned long x; 196 char *s, *e; 197 uint64_t i; 198 double d; 199 200 errno = 0; 201 202 switch (ucv_type(v)) { 203 case UC_INTEGER: 204 i = ucv_uint64_get(v); 205 206 if (i > ULONG_MAX) 207 errno = ERANGE; 208 209 x = (unsigned long)i; 210 break; 211 212 case UC_DOUBLE: 213 d = ucv_double_get(v); 214 x = (unsigned long)d; 215 216 if (isnan(d) || d < 0 || d > (double)ULONG_MAX || d - x != 0) 217 errno = ERANGE; 218 219 break; 220 221 case UC_BOOLEAN: 222 x = (unsigned long)ucv_boolean_get(v); 223 break; 224 225 case UC_NULL: 226 x = 0; 227 break; 228 229 case UC_STRING: 230 s = ucv_string_get(v); 231 x = strtoul(s, &e, 0); 232 233 if (e == s || *e != '\0') 234 errno = EINVAL; 235 236 break; 237 238 default: 239 errno = EINVAL; 240 x = 0; 241 break; 242 } 243 244 if (errno != 0) { 245 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 246 (errno == ERANGE) 247 ? "Argument out of range" 248 : "Argument not convertible to number"); 249 250 return false; 251 } 252 253 *p = x; 254 255 return true; 256 } 257 258 static bool 259 ucv_as_longlong(uc_vm_t *vm, uc_value_t *v, long long *p) 260 { 261 char *s, *e; 262 long long x; 263 int64_t i; 264 double d; 265 266 errno = 0; 267 268 switch (ucv_type(v)) { 269 case UC_INTEGER: 270 i = ucv_int64_get(v); 271 272 if (i < LLONG_MIN || i > LLONG_MAX) 273 errno = ERANGE; 274 275 x = (long long)i; 276 break; 277 278 case UC_DOUBLE: 279 d = ucv_double_get(v); 280 x = (long long)d; 281 282 if (isnan(d) || d < (double)LLONG_MIN || d > (double)LLONG_MAX || d - x != 0) 283 errno = ERANGE; 284 285 break; 286 287 case UC_BOOLEAN: 288 x = (long long)ucv_boolean_get(v); 289 break; 290 291 case UC_NULL: 292 x = 0; 293 break; 294 295 case UC_STRING: 296 s = ucv_string_get(v); 297 x = strtoll(s, &e, 0); 298 299 if (e == s || *e != '\0') 300 errno = EINVAL; 301 302 break; 303 304 default: 305 errno = EINVAL; 306 x = 0; 307 break; 308 } 309 310 if (errno != 0) { 311 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 312 (errno == ERANGE) 313 ? "Argument out of range" 314 : "Argument not convertible to number"); 315 316 return false; 317 } 318 319 *p = x; 320 321 return true; 322 } 323 324 static bool 325 ucv_as_ulonglong(uc_vm_t *vm, uc_value_t *v, unsigned long long *p) 326 { 327 unsigned long long x; 328 char *s, *e; 329 uint64_t i; 330 double d; 331 332 errno = 0; 333 334 switch (ucv_type(v)) { 335 case UC_INTEGER: 336 i = ucv_uint64_get(v); 337 338 if (i > ULLONG_MAX) 339 errno = ERANGE; 340 341 x = (unsigned long long)i; 342 break; 343 344 case UC_DOUBLE: 345 d = ucv_double_get(v); 346 x = (unsigned long long)d; 347 348 if (isnan(d) || d < 0 || d > (double)ULLONG_MAX || d - x != 0) 349 errno = ERANGE; 350 351 break; 352 353 case UC_BOOLEAN: 354 x = (unsigned long long)ucv_boolean_get(v); 355 break; 356 357 case UC_NULL: 358 x = 0; 359 break; 360 361 case UC_STRING: 362 s = ucv_string_get(v); 363 x = strtoull(s, &e, 0); 364 365 if (e == s || *e != '\0') 366 errno = EINVAL; 367 368 break; 369 370 default: 371 errno = EINVAL; 372 x = 0; 373 break; 374 } 375 376 if (errno != 0) { 377 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 378 (errno == ERANGE) 379 ? "Argument out of range" 380 : "Argument not convertible to number"); 381 382 return false; 383 } 384 385 *p = x; 386 387 return true; 388 } 389 390 static bool 391 ucv_as_ssize_t(uc_vm_t *vm, uc_value_t *v, ssize_t *p) 392 { 393 char *s, *e; 394 int64_t i; 395 ssize_t x; 396 double d; 397 398 errno = 0; 399 400 switch (ucv_type(v)) { 401 case UC_INTEGER: 402 i = ucv_int64_get(v); 403 404 if (i < -1 || i > SSIZE_MAX) 405 errno = ERANGE; 406 407 x = (ssize_t)i; 408 break; 409 410 case UC_DOUBLE: 411 d = ucv_double_get(v); 412 x = (ssize_t)d; 413 414 if (isnan(d) || d < -1 || d > (double)SSIZE_MAX || d - x != 0) 415 errno = ERANGE; 416 417 break; 418 419 case UC_BOOLEAN: 420 x = (ssize_t)ucv_boolean_get(v); 421 break; 422 423 case UC_NULL: 424 x = 0; 425 break; 426 427 case UC_STRING: 428 s = ucv_string_get(v); 429 i = strtoll(s, &e, 0); 430 431 if (e == s || *e != '\0') 432 errno = EINVAL; 433 else if (i < -1 || i > SSIZE_MAX) 434 errno = ERANGE; 435 436 x = (ssize_t)i; 437 break; 438 439 default: 440 errno = EINVAL; 441 x = 0; 442 break; 443 } 444 445 if (errno != 0) { 446 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 447 (errno == ERANGE) 448 ? "Argument out of range" 449 : "Argument not convertible to number"); 450 451 return false; 452 } 453 454 *p = x; 455 456 return true; 457 } 458 459 /* Same, but handling size_t */ 460 461 static bool 462 ucv_as_size_t(uc_vm_t *vm, uc_value_t *v, size_t *p) 463 { 464 char *s, *e; 465 uint64_t i; 466 double d; 467 size_t x; 468 469 errno = 0; 470 471 switch (ucv_type(v)) { 472 case UC_INTEGER: 473 i = ucv_uint64_get(v); 474 475 if (i > SIZE_MAX) 476 errno = ERANGE; 477 478 x = (size_t)i; 479 break; 480 481 case UC_DOUBLE: 482 d = ucv_double_get(v); 483 x = (size_t)d; 484 485 if (isnan(d) || d < 0 || d > (double)SIZE_MAX || d - x != 0) 486 errno = ERANGE; 487 488 break; 489 490 case UC_BOOLEAN: 491 x = (size_t)ucv_boolean_get(v); 492 break; 493 494 case UC_NULL: 495 x = 0; 496 break; 497 498 case UC_STRING: 499 s = ucv_string_get(v); 500 i = strtoull(s, &e, 0); 501 502 if (e == s || *e != '\0') 503 errno = EINVAL; 504 else if (i > SIZE_MAX) 505 errno = ERANGE; 506 507 x = (size_t)i; 508 break; 509 510 default: 511 errno = EINVAL; 512 x = 0; 513 break; 514 } 515 516 if (errno != 0) { 517 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 518 (errno == ERANGE) 519 ? "Argument out of range" 520 : "Argument not convertible to number"); 521 522 return false; 523 } 524 525 *p = x; 526 527 return true; 528 } 529 530 static bool 531 ucv_as_double(uc_vm_t *vm, uc_value_t *v, double *p) 532 { 533 char *s, *e; 534 int64_t i; 535 double x; 536 537 errno = 0; 538 539 switch (ucv_type(v)) { 540 case UC_INTEGER: 541 i = ucv_int64_get(v); 542 543 if (errno == 0) { 544 if (i < -DBL_MAX || i > DBL_MAX) 545 errno = ERANGE; 546 } 547 548 x = (double)i; 549 break; 550 551 case UC_DOUBLE: 552 x = ucv_double_get(v); 553 break; 554 555 case UC_BOOLEAN: 556 x = (double)ucv_boolean_get(v); 557 break; 558 559 case UC_NULL: 560 x = 0.0; 561 break; 562 563 case UC_STRING: 564 s = ucv_string_get(v); 565 x = strtod(s, &e); 566 567 if (e == s || *e != '\0') 568 errno = EINVAL; 569 570 break; 571 572 default: 573 errno = EINVAL; 574 x = 0.0; 575 break; 576 } 577 578 if (errno != 0) { 579 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 580 (errno == ERANGE) 581 ? "Argument out of range" 582 : "Argument not convertible to number"); 583 584 return false; 585 } 586 587 *p = x; 588 589 return true; 590 } 591 592 593 /* Floating point helpers */ 594 595 static bool 596 double_pack16(double d, char *buf, bool little_endian) 597 { 598 int32_t exponent = 0; 599 uint16_t bits = 0; 600 bool sign = false; 601 double fraction; 602 uint8_t *p; 603 604 if (d == 0.0) { 605 sign = (copysign(1.0, d) == -1.0); 606 } 607 else if (isnan(d)) { 608 sign = (copysign(1.0, d) == -1.0); 609 exponent = 0x1f; 610 bits = 512; 611 } 612 else if (!isfinite(d)) { 613 sign = (d < 0.0); 614 exponent = 0x1f; 615 } 616 else { 617 if (d < 0.0) { 618 sign = true; 619 d = -d; 620 } 621 622 fraction = frexp(d, &exponent); 623 624 assert(fraction >= 0.5 && fraction < 1.0); 625 626 fraction *= 2.0; 627 exponent--; 628 629 if (exponent >= 16) { 630 errno = ERANGE; 631 632 return false; 633 } 634 else if (exponent < -25) { 635 fraction = 0.0; 636 exponent = 0; 637 } 638 else if (exponent < -14) { 639 fraction = ldexp(fraction, 14 + exponent); 640 exponent = 0; 641 } 642 else { 643 fraction -= 1.0; 644 exponent += 15; 645 } 646 647 fraction *= 1024.0; 648 bits = (uint16_t)fraction; 649 650 assert(bits < 1024); 651 assert(exponent < 31); 652 653 if ((fraction - bits > 0.5) || ((fraction - bits == 0.5) && (bits % 2))) { 654 if (++bits == 1024) { 655 bits = 0; 656 657 if (++exponent == 31) { 658 errno = ERANGE; 659 660 return false; 661 } 662 } 663 } 664 } 665 666 bits |= (exponent << 10) | (sign << 15); 667 668 p = (uint8_t *)buf + little_endian; 669 *p = (bits >> 8) & 0xff; 670 671 p += (little_endian ? -1 : 1); 672 *p = bits & 0xff; 673 674 return true; 675 } 676 677 static bool 678 double_pack32(double d, char *buf, bool little_endian) 679 { 680 int8_t step = little_endian ? -1 : 1; 681 int32_t exponent = 0; 682 uint32_t bits = 0; 683 bool sign = false; 684 double fraction; 685 uint8_t *p; 686 687 if (d == 0.0) { 688 sign = (copysign(1.0, d) == -1.0); 689 } 690 else if (isnan(d)) { 691 sign = (copysign(1.0, d) == -1.0); 692 exponent = 0xff; 693 bits = 0x7fffff; 694 } 695 else if (!isfinite(d)) { 696 sign = (d < 0.0); 697 exponent = 0xff; 698 } 699 else { 700 if (d < 0.0) { 701 sign = true; 702 d = -d; 703 } 704 705 fraction = frexp(d, &exponent); 706 707 if (fraction == 0.0) { 708 exponent = 0; 709 } 710 else { 711 assert(fraction >= 0.5 && fraction < 1.0); 712 713 fraction *= 2.0; 714 exponent--; 715 } 716 717 if (exponent >= 128) { 718 errno = ERANGE; 719 720 return false; 721 } 722 else if (exponent < -126) { 723 fraction = ldexp(fraction, 126 + exponent); 724 exponent = 0; 725 } 726 else if (exponent != 0 || fraction != 0.0) { 727 fraction -= 1.0; 728 exponent += 127; 729 } 730 731 fraction *= 8388608.0; 732 bits = (uint32_t)(fraction + 0.5); 733 734 assert(bits <= 8388608); 735 736 if (bits >> 23) { 737 bits = 0; 738 739 if (++exponent >= 255) { 740 errno = ERANGE; 741 742 return false; 743 } 744 } 745 } 746 747 p = (uint8_t *)buf + (little_endian ? 3 : 0); 748 *p = (sign << 7) | (exponent >> 1); 749 750 p += step; 751 *p = ((exponent & 1) << 7) | (bits >> 16); 752 753 p += step; 754 *p = (bits >> 8) & 0xff; 755 756 p += step; 757 *p = bits & 0xff; 758 759 return true; 760 } 761 762 #define double_pack64 uc_double_pack 763 764 static double 765 double_unpack16(const char *buf, bool little_endian) 766 { 767 uint32_t fraction; 768 int32_t exponent; 769 uint8_t *p; 770 bool sign; 771 double d; 772 773 p = (uint8_t *)buf + little_endian; 774 sign = (*p >> 7) & 1; 775 exponent = (*p & 0x7c) >> 2; 776 fraction = (*p & 0x03) << 8; 777 778 p += little_endian ? -1 : 1; 779 fraction |= *p; 780 781 if (exponent == 0x1f) { 782 if (fraction == 0) 783 return sign ? -INFINITY : INFINITY; 784 else 785 return sign ? -NAN : NAN; 786 } 787 788 d = (double)fraction / 1024.0; 789 790 if (exponent == 0) { 791 exponent = -14; 792 } 793 else { 794 exponent -= 15; 795 d += 1.0; 796 } 797 798 d = ldexp(d, exponent); 799 800 return sign ? -d : d; 801 } 802 803 static double 804 double_unpack32(const char *buf, bool little_endian) 805 { 806 int8_t step = little_endian ? -1 : 1; 807 uint32_t fraction; 808 int32_t exponent; 809 uint8_t *p; 810 bool sign; 811 double d; 812 813 p = (uint8_t *)buf + (little_endian ? 3 : 0); 814 sign = (*p >> 7) & 1; 815 exponent = (*p & 0x7f) << 1; 816 817 p += step; 818 exponent |= (*p >> 7) & 1; 819 fraction = (*p & 0x7f) << 16; 820 821 p += step; 822 fraction |= *p << 8; 823 824 p += step; 825 fraction |= *p; 826 827 if (exponent == 0xff) { 828 if (fraction == 0) 829 return sign ? -INFINITY : INFINITY; 830 else 831 return sign ? -NAN : NAN; 832 } 833 834 d = (double)fraction / 8388608.0; 835 836 if (exponent == 0) { 837 exponent = -126; 838 } 839 else { 840 exponent -= 127; 841 d += 1.0; 842 } 843 844 d = ldexp(d, exponent); 845 846 return sign ? -d : d; 847 } 848 849 #define double_unpack64 uc_double_unpack 850 851 static bool 852 range_exception(uc_vm_t *vm, const formatdef_t *f, bool is_unsigned) 853 { 854 /* ulargest is the largest unsigned value with f->size bytes. 855 * Note that the simpler: 856 * ((size_t)1 << (f->size * 8)) - 1 857 * doesn't work when f->size == sizeof(size_t) because C doesn't 858 * define what happens when a left shift count is >= the number of 859 * bits in the integer being shifted; e.g., on some boxes it doesn't 860 * shift at all when they're equal. 861 */ 862 const size_t ulargest = (size_t)-1 >> ((sizeof(size_t) - f->size)*8); 863 864 assert(f->size >= 1 && f->size <= (ssize_t)sizeof(size_t)); 865 866 if (is_unsigned) { 867 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 868 "Format '%c' requires numeric argument between 0 and %zu", 869 f->format, 870 ulargest); 871 } 872 else { 873 const ssize_t largest = (ssize_t)(ulargest >> 1); 874 875 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 876 "Format '%c' requires numeric argument between %zd and %zd", 877 f->format, 878 ~ largest, 879 largest); 880 } 881 882 return false; 883 } 884 885 886 /* Native mode routines. ****************************************************/ 887 888 static uc_value_t * 889 native_unpack_char(uc_vm_t *vm, const char *p, const formatdef_t *f) 890 { 891 return ucv_string_new_length(p, 1); 892 } 893 894 static uc_value_t * 895 native_unpack_byte(uc_vm_t *vm, const char *p, const formatdef_t *f) 896 { 897 return ucv_int64_new(*(signed char *)p); 898 } 899 900 static uc_value_t * 901 native_unpack_ubyte(uc_vm_t *vm, const char *p, const formatdef_t *f) 902 { 903 return ucv_uint64_new(*(unsigned char *)p); 904 } 905 906 static uc_value_t * 907 native_unpack_short(uc_vm_t *vm, const char *p, const formatdef_t *f) 908 { 909 short x = 0; 910 911 memcpy(&x, p, sizeof(x)); 912 913 return ucv_int64_new(x); 914 } 915 916 static uc_value_t * 917 native_unpack_ushort(uc_vm_t *vm, const char *p, const formatdef_t *f) 918 { 919 unsigned short x = 0; 920 921 memcpy(&x, p, sizeof(x)); 922 923 return ucv_uint64_new(x); 924 } 925 926 static uc_value_t * 927 native_unpack_int(uc_vm_t *vm, const char *p, const formatdef_t *f) 928 { 929 int x = 0; 930 931 memcpy(&x, p, sizeof(x)); 932 933 return ucv_int64_new(x); 934 } 935 936 static uc_value_t * 937 native_unpack_uint(uc_vm_t *vm, const char *p, const formatdef_t *f) 938 { 939 unsigned int x = 0; 940 941 memcpy(&x, p, sizeof(x)); 942 943 return ucv_uint64_new(x); 944 } 945 946 static uc_value_t * 947 native_unpack_long(uc_vm_t *vm, const char *p, const formatdef_t *f) 948 { 949 long x = 0; 950 951 memcpy(&x, p, sizeof(x)); 952 953 return ucv_int64_new(x); 954 } 955 956 static uc_value_t * 957 native_unpack_ulong(uc_vm_t *vm, const char *p, const formatdef_t *f) 958 { 959 unsigned long x = 0; 960 961 memcpy(&x, p, sizeof(x)); 962 963 return ucv_uint64_new(x); 964 } 965 966 static uc_value_t * 967 native_unpack_ssize_t(uc_vm_t *vm, const char *p, const formatdef_t *f) 968 { 969 ssize_t x = 0; 970 971 memcpy(&x, p, sizeof(x)); 972 973 return ucv_int64_new(x); 974 } 975 976 static uc_value_t * 977 native_unpack_size_t(uc_vm_t *vm, const char *p, const formatdef_t *f) 978 { 979 size_t x = 0; 980 981 memcpy(&x, p, sizeof(x)); 982 983 return ucv_uint64_new(x); 984 } 985 986 static uc_value_t * 987 native_unpack_longlong(uc_vm_t *vm, const char *p, const formatdef_t *f) 988 { 989 long long x = 0; 990 991 memcpy(&x, p, sizeof(x)); 992 993 return ucv_int64_new(x); 994 } 995 996 static uc_value_t * 997 native_unpack_ulonglong(uc_vm_t *vm, const char *p, const formatdef_t *f) 998 { 999 unsigned long long x = 0; 1000 1001 memcpy(&x, p, sizeof(x)); 1002 1003 return ucv_uint64_new(x); 1004 } 1005 1006 static uc_value_t * 1007 native_unpack_bool(uc_vm_t *vm, const char *p, const formatdef_t *f) 1008 { 1009 bool x = false; 1010 1011 memcpy(&x, p, sizeof(x)); 1012 1013 return ucv_boolean_new(x != 0); 1014 } 1015 1016 1017 static uc_value_t * 1018 native_unpack_halffloat(uc_vm_t *vm, const char *p, const formatdef_t *f) 1019 { 1020 #if __BYTE_ORDER == __LITTLE_ENDIAN 1021 return ucv_double_new(double_unpack16(p, true)); 1022 #else 1023 return ucv_double_new(double_unpack16(p, false)); 1024 #endif 1025 } 1026 1027 static uc_value_t * 1028 native_unpack_float(uc_vm_t *vm, const char *p, const formatdef_t *f) 1029 { 1030 float x = 0.0; 1031 1032 memcpy(&x, p, sizeof(x)); 1033 1034 return ucv_double_new(x); 1035 } 1036 1037 static uc_value_t * 1038 native_unpack_double(uc_vm_t *vm, const char *p, const formatdef_t *f) 1039 { 1040 double x = 0.0; 1041 1042 memcpy(&x, p, sizeof(x)); 1043 1044 return ucv_double_new(x); 1045 } 1046 1047 static uc_value_t * 1048 native_unpack_void_p(uc_vm_t *vm, const char *p, const formatdef_t *f) 1049 { 1050 void *x = NULL; 1051 1052 memcpy(&x, p, sizeof(x)); 1053 1054 return ucv_int64_new((intptr_t)x); 1055 } 1056 1057 static bool 1058 native_pack_byte(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1059 { 1060 long x = 0; 1061 1062 if (!ucv_as_long(vm, v, &x)) 1063 return false; 1064 1065 if (x < -128 || x > 127) { 1066 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 1067 "Byte format requires numeric value between -128 and 127"); 1068 1069 return false; 1070 } 1071 1072 *p = (char)x; 1073 1074 return true; 1075 } 1076 1077 static bool 1078 native_pack_ubyte(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1079 { 1080 long x = 0; 1081 1082 if (!ucv_as_long(vm, v, &x)) 1083 return false; 1084 1085 if (x < 0 || x > 255) { 1086 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 1087 "Unsigned byte format requires numeric value between 0 and 255"); 1088 1089 return false; 1090 } 1091 1092 *(unsigned char *)p = (unsigned char)x; 1093 1094 return true; 1095 } 1096 1097 static bool 1098 native_pack_char(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1099 { 1100 char *s = NULL; 1101 1102 if (ucv_type(v) == UC_STRING) { 1103 s = ucv_string_get(v); 1104 *p = *s; 1105 } 1106 else { 1107 s = ucv_to_string(vm, v); 1108 *p = *s; 1109 free(s); 1110 } 1111 1112 return true; 1113 } 1114 1115 static bool 1116 native_pack_short(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1117 { 1118 long x = 0; 1119 short y = 0; 1120 1121 if (!ucv_as_long(vm, v, &x)) 1122 return false; 1123 1124 if (x < SHRT_MIN || x > SHRT_MAX) { 1125 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 1126 "Short format requires numeric value between %d and %d", 1127 (int)SHRT_MIN, (int)SHRT_MAX); 1128 1129 return false; 1130 } 1131 1132 y = (short)x; 1133 memcpy(p, &y, sizeof(y)); 1134 1135 return true; 1136 } 1137 1138 static bool 1139 native_pack_ushort(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1140 { 1141 unsigned short y = 0; 1142 long x = 0; 1143 1144 if (!ucv_as_long(vm, v, &x)) 1145 return false; 1146 1147 if (x < 0 || x > USHRT_MAX) { 1148 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 1149 "Unsigned short format requires numeric value between 0 and %u", 1150 (unsigned int)USHRT_MAX); 1151 1152 return false; 1153 } 1154 1155 y = (unsigned short)x; 1156 memcpy(p, &y, sizeof(y)); 1157 1158 return true; 1159 } 1160 1161 static bool 1162 native_pack_int(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1163 { 1164 long x = 0; 1165 int y = 0; 1166 1167 if (!ucv_as_long(vm, v, &x)) 1168 return false; 1169 1170 if (sizeof(long) > sizeof(int)) { 1171 if ((x < ((long)INT_MIN)) || (x > ((long)INT_MAX))) 1172 return range_exception(vm, f, false); 1173 } 1174 1175 y = (int)x; 1176 memcpy(p, &y, sizeof(y)); 1177 1178 return true; 1179 } 1180 1181 static bool 1182 native_pack_uint(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1183 { 1184 unsigned long x = 0; 1185 unsigned int y = 0; 1186 1187 if (!ucv_as_ulong(vm, v, &x)) 1188 return false; 1189 1190 if (sizeof(long) > sizeof(int)) { 1191 if (x > ((unsigned long)UINT_MAX)) 1192 return range_exception(vm, f, true); 1193 } 1194 1195 y = (unsigned int)x; 1196 memcpy(p, &y, sizeof(y)); 1197 1198 return true; 1199 } 1200 1201 static bool 1202 native_pack_long(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1203 { 1204 long x = 0; 1205 1206 if (!ucv_as_long(vm, v, &x)) 1207 return false; 1208 1209 memcpy(p, &x, sizeof(x)); 1210 1211 return true; 1212 } 1213 1214 static bool 1215 native_pack_ulong(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1216 { 1217 unsigned long x = 0; 1218 1219 if (!ucv_as_ulong(vm, v, &x)) 1220 return false; 1221 1222 memcpy(p, &x, sizeof(x)); 1223 1224 return true; 1225 } 1226 1227 static bool 1228 native_pack_ssize_t(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1229 { 1230 ssize_t x = 0; 1231 1232 if (!ucv_as_ssize_t(vm, v, &x)) 1233 return false; 1234 1235 memcpy(p, &x, sizeof(x)); 1236 1237 return true; 1238 } 1239 1240 static bool 1241 native_pack_size_t(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1242 { 1243 size_t x = 0; 1244 1245 if (!ucv_as_size_t(vm, v, &x)) 1246 return false; 1247 1248 memcpy(p, &x, sizeof(x)); 1249 1250 return true; 1251 } 1252 1253 static bool 1254 native_pack_longlong(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1255 { 1256 long long x = 0; 1257 1258 if (!ucv_as_longlong(vm, v, &x)) 1259 return false; 1260 1261 memcpy(p, &x, sizeof(x)); 1262 1263 return true; 1264 } 1265 1266 static bool 1267 native_pack_ulonglong(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1268 { 1269 unsigned long long x = 0; 1270 1271 if (!ucv_as_ulonglong(vm, v, &x)) 1272 return false; 1273 1274 memcpy(p, &x, sizeof(x)); 1275 1276 return true; 1277 } 1278 1279 1280 static bool 1281 native_pack_bool(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1282 { 1283 bool x = 0; 1284 1285 x = ucv_is_truish(v); 1286 1287 memcpy(p, &x, sizeof(x)); 1288 1289 return true; 1290 } 1291 1292 static bool 1293 native_pack_halffloat(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1294 { 1295 double x; 1296 1297 if (!ucv_as_double(vm, v, &x)) 1298 return false; 1299 1300 #if __BYTE_ORDER == __LITTLE_ENDIAN 1301 return double_pack16(x, p, true); 1302 #else 1303 return double_pack16(x, p, false); 1304 #endif 1305 } 1306 1307 static bool 1308 native_pack_float(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1309 { 1310 double d = 0.0; 1311 float x = 0.0; 1312 1313 if (!ucv_as_double(vm, v, &d)) 1314 return false; 1315 1316 x = (float)d; 1317 memcpy(p, &x, sizeof(x)); 1318 1319 return true; 1320 } 1321 1322 static bool 1323 native_pack_double(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1324 { 1325 double x = 0.0; 1326 1327 if (!ucv_as_double(vm, v, &x)) 1328 return false; 1329 1330 memcpy(p, &x, sizeof(x)); 1331 1332 return true; 1333 } 1334 1335 static bool 1336 native_pack_void_p(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1337 { 1338 long long int i = 0; 1339 void *x = NULL; 1340 1341 if (!ucv_as_longlong(vm, v, &i)) 1342 return false; 1343 1344 x = (void *)(intptr_t)i; 1345 memcpy(p, &x, sizeof(x)); 1346 1347 return true; 1348 } 1349 1350 static const formatdef_t native_endian_table[] = { 1351 { 'x', sizeof(char), 0, NULL, NULL }, 1352 { 'b', sizeof(char), 0, native_unpack_byte, native_pack_byte }, 1353 { 'B', sizeof(char), 0, native_unpack_ubyte, native_pack_ubyte }, 1354 { 'c', sizeof(char), 0, native_unpack_char, native_pack_char }, 1355 { '*', sizeof(char), 0, NULL, NULL }, 1356 { 's', sizeof(char), 0, NULL, NULL }, 1357 { 'p', sizeof(char), 0, NULL, NULL }, 1358 { 'h', sizeof(short), SHORT_ALIGN, native_unpack_short, native_pack_short }, 1359 { 'H', sizeof(short), SHORT_ALIGN, native_unpack_ushort, native_pack_ushort }, 1360 { 'i', sizeof(int), INT_ALIGN, native_unpack_int, native_pack_int }, 1361 { 'I', sizeof(int), INT_ALIGN, native_unpack_uint, native_pack_uint }, 1362 { 'l', sizeof(long), LONG_ALIGN, native_unpack_long, native_pack_long }, 1363 { 'L', sizeof(long), LONG_ALIGN, native_unpack_ulong, native_pack_ulong }, 1364 { 'n', sizeof(size_t), SIZE_T_ALIGN, native_unpack_ssize_t, native_pack_ssize_t }, 1365 { 'N', sizeof(size_t), SIZE_T_ALIGN, native_unpack_size_t, native_pack_size_t }, 1366 { 'q', sizeof(long long), LONG_LONG_ALIGN, native_unpack_longlong, native_pack_longlong }, 1367 { 'Q', sizeof(long long), LONG_LONG_ALIGN, native_unpack_ulonglong,native_pack_ulonglong }, 1368 { '?', sizeof(bool), BOOL_ALIGN, native_unpack_bool, native_pack_bool }, 1369 { 'e', sizeof(short), SHORT_ALIGN, native_unpack_halffloat, native_pack_halffloat }, 1370 { 'f', sizeof(float), FLOAT_ALIGN, native_unpack_float, native_pack_float }, 1371 { 'd', sizeof(double), DOUBLE_ALIGN, native_unpack_double, native_pack_double }, 1372 { 'P', sizeof(void *), VOID_P_ALIGN, native_unpack_void_p, native_pack_void_p }, 1373 { 0 } 1374 }; 1375 1376 1377 /* Big-endian routines. *****************************************************/ 1378 1379 static uc_value_t * 1380 be_unpack_int(uc_vm_t *vm, const char *p, const formatdef_t *f) 1381 { 1382 const unsigned char *bytes = (const unsigned char *)p; 1383 ssize_t i = f->size; 1384 long x = 0; 1385 1386 do { 1387 x = (x<<8) | *bytes++; 1388 } while (--i > 0); 1389 1390 /* Extend the sign bit. */ 1391 if ((ssize_t)sizeof(long) > f->size) 1392 x |= -(x & (1L << ((8 * f->size) - 1))); 1393 1394 return ucv_int64_new(x); 1395 } 1396 1397 static uc_value_t * 1398 be_unpack_uint(uc_vm_t *vm, const char *p, const formatdef_t *f) 1399 { 1400 const unsigned char *bytes = (const unsigned char *)p; 1401 ssize_t i = f->size; 1402 unsigned long x = 0; 1403 1404 do { 1405 x = (x<<8) | *bytes++; 1406 } while (--i > 0); 1407 1408 return ucv_uint64_new(x); 1409 } 1410 1411 static uc_value_t * 1412 be_unpack_longlong(uc_vm_t *vm, const char *p, const formatdef_t *f) 1413 { 1414 const unsigned char *bytes = (const unsigned char *)p; 1415 ssize_t i = f->size; 1416 long long x = 0; 1417 1418 do { 1419 x = (x<<8) | *bytes++; 1420 } while (--i > 0); 1421 1422 /* Extend the sign bit. */ 1423 if ((ssize_t)sizeof(long long) > f->size) 1424 x |= -(x & ((long long)1 << ((8 * f->size) - 1))); 1425 1426 return ucv_int64_new(x); 1427 } 1428 1429 static uc_value_t * 1430 be_unpack_ulonglong(uc_vm_t *vm, const char *p, const formatdef_t *f) 1431 { 1432 const unsigned char *bytes = (const unsigned char *)p; 1433 unsigned long long x = 0; 1434 ssize_t i = f->size; 1435 1436 do { 1437 x = (x<<8) | *bytes++; 1438 } while (--i > 0); 1439 1440 return ucv_uint64_new(x); 1441 } 1442 1443 static uc_value_t * 1444 be_unpack_halffloat(uc_vm_t *vm, const char *p, const formatdef_t *f) 1445 { 1446 return ucv_double_new(double_unpack16(p, false)); 1447 } 1448 1449 static uc_value_t * 1450 be_unpack_float(uc_vm_t *vm, const char *p, const formatdef_t *f) 1451 { 1452 return ucv_double_new(double_unpack32(p, false)); 1453 } 1454 1455 static uc_value_t * 1456 be_unpack_double(uc_vm_t *vm, const char *p, const formatdef_t *f) 1457 { 1458 return ucv_double_new(double_unpack64(p, false)); 1459 } 1460 1461 static uc_value_t * 1462 be_unpack_bool(uc_vm_t *vm, const char *p, const formatdef_t *f) 1463 { 1464 return ucv_boolean_new(*p != 0); 1465 } 1466 1467 static bool 1468 be_pack_int(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1469 { 1470 unsigned char *q = (unsigned char *)p; 1471 ssize_t i = 0; 1472 long x = 0; 1473 1474 if (!ucv_as_long(vm, v, &x)) 1475 return false; 1476 1477 i = f->size; 1478 1479 if (i != sizeof(long)) { 1480 if ((i == 2) && (x < -32768 || x > 32767)) 1481 return range_exception(vm, f, false); 1482 #if UINT_MAX < ULONG_MAX 1483 else if ((i == 4) && (x < -2147483648L || x > 2147483647L)) 1484 return range_exception(vm, f, false); 1485 #endif 1486 } 1487 1488 do { 1489 q[--i] = (unsigned char)(x & 0xffL); 1490 x >>= 8; 1491 } while (i > 0); 1492 1493 return true; 1494 } 1495 1496 static bool 1497 be_pack_uint(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1498 { 1499 unsigned char *q = (unsigned char *)p; 1500 unsigned long x = 0; 1501 ssize_t i = 0; 1502 1503 if (!ucv_as_ulong(vm, v, &x)) 1504 return false; 1505 1506 i = f->size; 1507 1508 if (i != sizeof(long)) { 1509 unsigned long maxint = 1; 1510 maxint <<= (unsigned long)(i * 8); 1511 if (x >= maxint) 1512 return range_exception(vm, f, true); 1513 } 1514 1515 do { 1516 q[--i] = (unsigned char)(x & 0xffUL); 1517 x >>= 8; 1518 } while (i > 0); 1519 1520 return true; 1521 } 1522 1523 static bool 1524 be_pack_longlong(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1525 { 1526 unsigned char *q = (unsigned char *)p; 1527 long long x = 0; 1528 ssize_t i = 0; 1529 1530 if (!ucv_as_longlong(vm, v, &x)) 1531 return false; 1532 1533 i = f->size; 1534 1535 do { 1536 q[--i] = (unsigned char)(x & 0xffL); 1537 x >>= 8; 1538 } while (i > 0); 1539 1540 return true; 1541 } 1542 1543 static bool 1544 be_pack_ulonglong(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1545 { 1546 unsigned char *q = (unsigned char *)p; 1547 unsigned long long x = 0; 1548 ssize_t i = 0; 1549 1550 if (!ucv_as_ulonglong(vm, v, &x)) 1551 return false; 1552 1553 i = f->size; 1554 1555 do { 1556 q[--i] = (unsigned char)(x & 0xffUL); 1557 x >>= 8; 1558 } while (i > 0); 1559 1560 return true; 1561 } 1562 1563 static bool 1564 be_pack_halffloat(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1565 { 1566 double x = 0.0; 1567 1568 if (!ucv_as_double(vm, v, &x)) 1569 return false; 1570 1571 return double_pack16(x, p, false); 1572 } 1573 1574 static bool 1575 be_pack_float(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1576 { 1577 double x = 0.0; 1578 1579 if (!ucv_as_double(vm, v, &x)) 1580 return false; 1581 1582 if (!double_pack32(x, p, 0)) { 1583 uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Argument out of range"); 1584 1585 return false; 1586 } 1587 1588 return true; 1589 } 1590 1591 static bool 1592 be_pack_double(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1593 { 1594 double x = 0.0; 1595 1596 if (!ucv_as_double(vm, v, &x)) 1597 return false; 1598 1599 if (!double_pack64(x, p, 0)) { 1600 uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Argument out of range"); 1601 1602 return false; 1603 } 1604 1605 return true; 1606 } 1607 1608 static bool 1609 be_pack_bool(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1610 { 1611 *p = (char)ucv_is_truish(v); 1612 1613 return true; 1614 } 1615 1616 static formatdef_t big_endian_table[] = { 1617 { 'x', 1, 0, NULL, NULL }, 1618 { 'b', 1, 0, native_unpack_byte, native_pack_byte }, 1619 { 'B', 1, 0, native_unpack_ubyte, native_pack_ubyte }, 1620 { 'c', 1, 0, native_unpack_char, native_pack_char }, 1621 { '*', 1, 0, NULL, NULL }, 1622 { 's', 1, 0, NULL, NULL }, 1623 { 'p', 1, 0, NULL, NULL }, 1624 { 'h', 2, 0, be_unpack_int, be_pack_int }, 1625 { 'H', 2, 0, be_unpack_uint, be_pack_uint }, 1626 { 'i', 4, 0, be_unpack_int, be_pack_int }, 1627 { 'I', 4, 0, be_unpack_uint, be_pack_uint }, 1628 { 'l', 4, 0, be_unpack_int, be_pack_int }, 1629 { 'L', 4, 0, be_unpack_uint, be_pack_uint }, 1630 { 'q', 8, 0, be_unpack_longlong, be_pack_longlong }, 1631 { 'Q', 8, 0, be_unpack_ulonglong, be_pack_ulonglong }, 1632 { '?', 1, 0, be_unpack_bool, be_pack_bool }, 1633 { 'e', 2, 0, be_unpack_halffloat, be_pack_halffloat }, 1634 { 'f', 4, 0, be_unpack_float, be_pack_float }, 1635 { 'd', 8, 0, be_unpack_double, be_pack_double }, 1636 { 0 } 1637 }; 1638 1639 1640 /* Little-endian routines. *****************************************************/ 1641 1642 static uc_value_t * 1643 le_unpack_int(uc_vm_t *vm, const char *p, const formatdef_t *f) 1644 { 1645 const unsigned char *bytes = (const unsigned char *)p; 1646 ssize_t i = f->size; 1647 long x = 0; 1648 1649 do { 1650 x = (x<<8) | bytes[--i]; 1651 } while (i > 0); 1652 1653 /* Extend the sign bit. */ 1654 if ((ssize_t)sizeof(long) > f->size) 1655 x |= -(x & (1L << ((8 * f->size) - 1))); 1656 1657 return ucv_int64_new(x); 1658 } 1659 1660 static uc_value_t * 1661 le_unpack_uint(uc_vm_t *vm, const char *p, const formatdef_t *f) 1662 { 1663 const unsigned char *bytes = (const unsigned char *)p; 1664 ssize_t i = f->size; 1665 unsigned long x = 0; 1666 1667 do { 1668 x = (x<<8) | bytes[--i]; 1669 } while (i > 0); 1670 1671 return ucv_uint64_new(x); 1672 } 1673 1674 static uc_value_t * 1675 le_unpack_longlong(uc_vm_t *vm, const char *p, const formatdef_t *f) 1676 { 1677 const unsigned char *bytes = (const unsigned char *)p; 1678 ssize_t i = f->size; 1679 long long x = 0; 1680 1681 do { 1682 x = (x<<8) | bytes[--i]; 1683 } while (i > 0); 1684 1685 /* Extend the sign bit. */ 1686 if ((ssize_t)sizeof(long long) > f->size) 1687 x |= -(x & ((long long)1 << ((8 * f->size) - 1))); 1688 1689 return ucv_int64_new(x); 1690 } 1691 1692 static uc_value_t * 1693 le_unpack_ulonglong(uc_vm_t *vm, const char *p, const formatdef_t *f) 1694 { 1695 const unsigned char *bytes = (const unsigned char *)p; 1696 unsigned long long x = 0; 1697 ssize_t i = f->size; 1698 1699 do { 1700 x = (x<<8) | bytes[--i]; 1701 } while (i > 0); 1702 1703 return ucv_uint64_new(x); 1704 } 1705 1706 static uc_value_t * 1707 le_unpack_halffloat(uc_vm_t *vm, const char *p, const formatdef_t *f) 1708 { 1709 return ucv_double_new(double_unpack16(p, true)); 1710 } 1711 1712 static uc_value_t * 1713 le_unpack_float(uc_vm_t *vm, const char *p, const formatdef_t *f) 1714 { 1715 return ucv_double_new(double_unpack32(p, true)); 1716 } 1717 1718 static uc_value_t * 1719 le_unpack_double(uc_vm_t *vm, const char *p, const formatdef_t *f) 1720 { 1721 return ucv_double_new(double_unpack64(p, true)); 1722 } 1723 1724 static bool 1725 le_pack_int(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1726 { 1727 unsigned char *q = (unsigned char *)p; 1728 ssize_t i = 0; 1729 long x = 0; 1730 1731 if (!ucv_as_long(vm, v, &x)) 1732 return false; 1733 1734 i = f->size; 1735 1736 if (i != sizeof(long)) { 1737 if ((i == 2) && (x < -32768 || x > 32767)) 1738 return range_exception(vm, f, false); 1739 #if UINT_MAX < ULONG_MAX 1740 else if ((i == 4) && (x < -2147483648L || x > 2147483647L)) 1741 return range_exception(vm, f, false); 1742 #endif 1743 } 1744 1745 do { 1746 *q++ = (unsigned char)(x & 0xffL); 1747 x >>= 8; 1748 } while (--i > 0); 1749 1750 return true; 1751 } 1752 1753 static bool 1754 le_pack_uint(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1755 { 1756 unsigned char *q = (unsigned char *)p; 1757 unsigned long x = 0; 1758 ssize_t i = 0; 1759 1760 if (!ucv_as_ulong(vm, v, &x)) 1761 return false; 1762 1763 i = f->size; 1764 1765 if (i != sizeof(long)) { 1766 unsigned long maxint = 1; 1767 maxint <<= (unsigned long)(i * 8); 1768 1769 if (x >= maxint) 1770 return range_exception(vm, f, true); 1771 } 1772 1773 do { 1774 *q++ = (unsigned char)(x & 0xffUL); 1775 x >>= 8; 1776 } while (--i > 0); 1777 1778 return true; 1779 } 1780 1781 static bool 1782 le_pack_longlong(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1783 { 1784 unsigned char *q = (unsigned char *)p; 1785 long long x = 0; 1786 ssize_t i = 0; 1787 1788 if (!ucv_as_longlong(vm, v, &x)) 1789 return false; 1790 1791 i = f->size; 1792 1793 do { 1794 *q++ = (unsigned char)(x & 0xffL); 1795 x >>= 8; 1796 } while (--i > 0); 1797 1798 return true; 1799 } 1800 1801 static bool 1802 le_pack_ulonglong(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1803 { 1804 unsigned char *q = (unsigned char *)p; 1805 unsigned long long x = 0; 1806 ssize_t i = 0; 1807 1808 if (!ucv_as_ulonglong(vm, v, &x)) 1809 return false; 1810 1811 i = f->size; 1812 1813 do { 1814 *q++ = (unsigned char)(x & 0xffUL); 1815 x >>= 8; 1816 } while (--i > 0); 1817 1818 return true; 1819 } 1820 1821 static bool 1822 le_pack_halffloat(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1823 { 1824 double x = 0.0; 1825 1826 if (!ucv_as_double(vm, v, &x)) 1827 return false; 1828 1829 return double_pack16(x, p, true); 1830 } 1831 1832 static bool 1833 le_pack_float(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1834 { 1835 double x = 0.0; 1836 1837 if (!ucv_as_double(vm, v, &x)) 1838 return false; 1839 1840 if (!double_pack32(x, p, 1)) { 1841 uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Argument out of range"); 1842 1843 return false; 1844 } 1845 1846 return true; 1847 } 1848 1849 static bool 1850 le_pack_double(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1851 { 1852 double x = 0.0; 1853 1854 if (!ucv_as_double(vm, v, &x)) 1855 return false; 1856 1857 if (!double_pack64(x, p, 1)) { 1858 uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Argument out of range"); 1859 1860 return false; 1861 } 1862 1863 return true; 1864 } 1865 1866 static formatdef_t little_endian_table[] = { 1867 { 'x', 1, 0, NULL, NULL }, 1868 { 'b', 1, 0, native_unpack_byte, native_pack_byte }, 1869 { 'B', 1, 0, native_unpack_ubyte, native_pack_ubyte }, 1870 { 'c', 1, 0, native_unpack_char, native_pack_char }, 1871 { '*', 1, 0, NULL, NULL }, 1872 { 's', 1, 0, NULL, NULL }, 1873 { 'p', 1, 0, NULL, NULL }, 1874 { 'h', 2, 0, le_unpack_int, le_pack_int }, 1875 { 'H', 2, 0, le_unpack_uint, le_pack_uint }, 1876 { 'i', 4, 0, le_unpack_int, le_pack_int }, 1877 { 'I', 4, 0, le_unpack_uint, le_pack_uint }, 1878 { 'l', 4, 0, le_unpack_int, le_pack_int }, 1879 { 'L', 4, 0, le_unpack_uint, le_pack_uint }, 1880 { 'q', 8, 0, le_unpack_longlong, le_pack_longlong }, 1881 { 'Q', 8, 0, le_unpack_ulonglong, le_pack_ulonglong }, 1882 { '?', 1, 0, be_unpack_bool, be_pack_bool }, 1883 { 'e', 2, 0, le_unpack_halffloat, le_pack_halffloat }, 1884 { 'f', 4, 0, le_unpack_float, le_pack_float }, 1885 { 'd', 8, 0, le_unpack_double, le_pack_double }, 1886 { 0 } 1887 }; 1888 1889 1890 static const formatdef_t * 1891 select_format_table(const char **pfmt) 1892 { 1893 const char *fmt = (*pfmt)++; /* May be backed out of later */ 1894 1895 switch (*fmt) { 1896 case '<': 1897 return little_endian_table; 1898 1899 case '>': 1900 case '!': /* Network byte order is big-endian */ 1901 return big_endian_table; 1902 1903 case '=': /* Host byte order -- different from native in alignment! */ 1904 #if __BYTE_ORDER == __LITTLE_ENDIAN 1905 return little_endian_table; 1906 #else 1907 return big_endian_table; 1908 #endif 1909 1910 default: 1911 --*pfmt; /* Back out of pointer increment */ 1912 /* Fall through */ 1913 1914 case '@': 1915 return native_endian_table; 1916 } 1917 } 1918 1919 1920 /* Get the table entry for a format code */ 1921 1922 static const formatdef_t * 1923 lookup_table_entry(uc_vm_t *vm, int c, const formatdef_t *table) 1924 { 1925 for (; table->format != '\0'; table++) { 1926 if (table->format == c) { 1927 return table; 1928 } 1929 } 1930 1931 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 1932 "Unrecognized character '%c' in struct format", 1933 c); 1934 1935 return NULL; 1936 } 1937 1938 1939 /* Align a size according to a format code. Return -1 on overflow. */ 1940 1941 static ssize_t 1942 align_for_entry(ssize_t size, const formatdef_t *e) 1943 { 1944 ssize_t extra; 1945 1946 if (e->alignment && size > 0) { 1947 extra = (e->alignment - 1) - (size - 1) % (e->alignment); 1948 1949 if (extra > SSIZE_MAX - size) 1950 return -1; 1951 1952 size += extra; 1953 } 1954 1955 return size; 1956 } 1957 1958 1959 static void 1960 optimize_functions(void) 1961 { 1962 /* Check endian and swap in faster functions */ 1963 const formatdef_t *native = native_endian_table; 1964 formatdef_t *other, *ptr; 1965 1966 #if __BYTE_ORDER == __LITTLE_ENDIAN 1967 other = little_endian_table; 1968 #else 1969 other = big_endian_table; 1970 #endif 1971 1972 /* Scan through the native table, find a matching 1973 entry in the endian table and swap in the 1974 native implementations whenever possible 1975 (64-bit platforms may not have "standard" sizes) */ 1976 while (native->format != '\0' && other->format != '\0') { 1977 ptr = other; 1978 1979 while (ptr->format != '\0') { 1980 if (ptr->format == native->format) { 1981 /* Match faster when formats are 1982 listed in the same order */ 1983 if (ptr == other) 1984 other++; 1985 1986 /* Only use the trick if the 1987 size matches */ 1988 if (ptr->size != native->size) 1989 break; 1990 1991 /* Skip float and double, could be 1992 "unknown" float format */ 1993 if (ptr->format == 'd' || ptr->format == 'f') 1994 break; 1995 1996 /* Skip bool, semantics are different for standard size */ 1997 if (ptr->format == '?') 1998 break; 1999 2000 ptr->pack = native->pack; 2001 ptr->unpack = native->unpack; 2002 break; 2003 } 2004 2005 ptr++; 2006 } 2007 2008 native++; 2009 } 2010 } 2011 2012 static formatstate_t * 2013 parse_format(uc_vm_t *vm, uc_value_t *fmtval) 2014 { 2015 ssize_t size, len, num, itemsize; 2016 const formatdef_t *e, *f; 2017 const char *fmt, *s; 2018 formatstate_t *state; 2019 formatcode_t *codes; 2020 size_t ncodes; 2021 char c; 2022 2023 if (ucv_type(fmtval) != UC_STRING) { 2024 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 2025 "Format value not a string"); 2026 2027 return NULL; 2028 } 2029 2030 fmt = ucv_string_get(fmtval); 2031 2032 if (strlen(fmt) != ucv_string_length(fmtval)) { 2033 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 2034 "Format string contains embedded null character"); 2035 2036 return NULL; 2037 } 2038 2039 f = select_format_table(&fmt); 2040 2041 s = fmt; 2042 size = 0; 2043 len = 0; 2044 ncodes = 0; 2045 2046 while ((c = *s++) != '\0') { 2047 if (isspace(c)) 2048 continue; 2049 2050 if ('' <= c && c <= '9') { 2051 num = c - ''; 2052 2053 while ('' <= (c = *s++) && c <= '9') { 2054 /* overflow-safe version of 2055 if (num*10 + (c - '') > SSIZE_MAX) { ... } */ 2056 if (num >= SSIZE_MAX / 10 && ( 2057 num > SSIZE_MAX / 10 || 2058 (c - '') > SSIZE_MAX % 10)) 2059 goto overflow; 2060 2061 num = num*10 + (c - ''); 2062 } 2063 2064 if (c == '\0') { 2065 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 2066 "Format string contains repeat count given without format specifier"); 2067 2068 return NULL; 2069 } 2070 } 2071 else 2072 num = 1; 2073 2074 e = lookup_table_entry(vm, c, f); 2075 2076 if (e == NULL) 2077 return NULL; 2078 2079 switch (c) { 2080 case '*': /* fall through */ 2081 case 's': 2082 case 'p': 2083 len++; 2084 ncodes++; 2085 break; 2086 2087 case 'x': 2088 break; 2089 2090 default: 2091 len += num; 2092 2093 if (num) 2094 ncodes++; 2095 2096 break; 2097 } 2098 2099 itemsize = e->size; 2100 size = align_for_entry(size, e); 2101 2102 if (size == -1) 2103 goto overflow; 2104 2105 /* if (size + num * itemsize > SSIZE_MAX) { ... } */ 2106 if (num > (SSIZE_MAX - size) / itemsize) 2107 goto overflow; 2108 2109 size += (c != '*') ? num * itemsize : 0; 2110 } 2111 2112 /* check for overflow */ 2113 if ((ncodes + 1) > ((size_t)SSIZE_MAX / sizeof(formatcode_t))) { 2114 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, "Out of memory"); 2115 2116 return NULL; 2117 } 2118 2119 state = xalloc(sizeof(*state) + ncodes * sizeof(formatcode_t)); 2120 state->len = len; 2121 state->size = size; 2122 state->ncodes = ncodes; 2123 2124 codes = state->codes; 2125 2126 s = fmt; 2127 size = 0; 2128 2129 while ((c = *s++) != '\0') { 2130 if (isspace(c)) 2131 continue; 2132 2133 if ('' <= c && c <= '9') { 2134 num = c - ''; 2135 2136 while ('' <= (c = *s++) && c <= '9') 2137 num = num*10 + (c - ''); 2138 2139 } 2140 else if (c == '*') 2141 num = -1; 2142 else 2143 num = 1; 2144 2145 e = lookup_table_entry(vm, c, f); 2146 2147 if (e == NULL) 2148 continue; 2149 2150 size = align_for_entry(size, e); 2151 2152 if (c == '*' || c == 's' || c == 'p') { 2153 codes->offset = size; 2154 codes->size = num; 2155 codes->fmtdef = e; 2156 codes->repeat = 1; 2157 codes++; 2158 size += (c != '*') ? num : 0; 2159 } 2160 else if (c == 'x') { 2161 size += num; 2162 } 2163 else if (num) { 2164 codes->offset = size; 2165 codes->size = e->size; 2166 codes->fmtdef = e; 2167 codes->repeat = num; 2168 codes++; 2169 size += e->size * num; 2170 } 2171 } 2172 2173 return state; 2174 2175 overflow: 2176 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, 2177 "Total struct size too long"); 2178 2179 return NULL; 2180 } 2181 2182 static uc_value_t * 2183 uc_pack_common(uc_vm_t *vm, size_t nargs, formatstate_t *state, size_t argoff) 2184 { 2185 size_t ncode, arg, off; 2186 formatcode_t *code; 2187 uc_string_t *buf; 2188 ssize_t size, n; 2189 const void *p; 2190 2191 for (ncode = 0, code = &state->codes[0], arg = argoff, off = 0; 2192 ncode < state->ncodes; 2193 code = &state->codes[++ncode]) { 2194 if (code->fmtdef->format == '*') { 2195 uc_value_t *v = uc_fn_arg(arg++); 2196 2197 if (ucv_type(v) != UC_STRING) 2198 continue; 2199 2200 n = ucv_string_length(v); 2201 2202 if (code->size == -1 || code->size > n) 2203 off += n; 2204 else 2205 off += code->size; 2206 } 2207 else { 2208 arg += code->repeat; 2209 } 2210 } 2211 2212 buf = xalloc(sizeof(*buf) + state->size + off + 1); 2213 buf->header.type = UC_STRING; 2214 buf->header.refcount = 1; 2215 buf->length = state->size + off; 2216 2217 for (ncode = 0, code = &state->codes[0], off = 0; 2218 ncode < state->ncodes; 2219 code = &state->codes[++ncode]) { 2220 const formatdef_t *e = code->fmtdef; 2221 char *res = buf->str + code->offset + off; 2222 ssize_t j = code->repeat; 2223 2224 while (j--) { 2225 uc_value_t *v = uc_fn_arg(argoff++); 2226 2227 size = code->size; 2228 2229 if (e->format == '*') { 2230 if (ucv_type(v) != UC_STRING) { 2231 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 2232 "Argument for '*' must be a string"); 2233 2234 goto err; 2235 } 2236 2237 n = ucv_string_length(v); 2238 p = ucv_string_get(v); 2239 2240 if (size == -1 || n < size) 2241 size = n; 2242 else if (n > size) 2243 n = size; 2244 2245 off += size; 2246 2247 if (n > 0) 2248 memcpy(res, p, n); 2249 } 2250 else if (e->format == 's') { 2251 if (ucv_type(v) != UC_STRING) { 2252 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 2253 "Argument for 's' must be a string"); 2254 2255 goto err; 2256 } 2257 2258 n = ucv_string_length(v); 2259 p = ucv_string_get(v); 2260 2261 if (n > size) 2262 n = size; 2263 2264 if (n > 0) 2265 memcpy(res, p, n); 2266 } 2267 else if (e->format == 'p') { 2268 if (ucv_type(v) != UC_STRING) { 2269 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 2270 "Argument for 'p' must be a string"); 2271 2272 goto err; 2273 } 2274 2275 n = ucv_string_length(v); 2276 p = ucv_string_get(v); 2277 2278 if (n > (size - 1)) 2279 n = size - 1; 2280 2281 if (n > 0) 2282 memcpy(res + 1, p, n); 2283 2284 if (n > 255) 2285 n = 255; 2286 2287 *res = (unsigned char)n; 2288 } 2289 else { 2290 if (!e->pack(vm, res, v, e)) 2291 goto err; 2292 } 2293 2294 res += size; 2295 } 2296 } 2297 2298 return &buf->header; 2299 2300 err: 2301 free(buf); 2302 2303 return NULL; 2304 } 2305 2306 static uc_value_t * 2307 uc_unpack_common(uc_vm_t *vm, size_t nargs, formatstate_t *state, size_t argoff) 2308 { 2309 uc_value_t *bufval = uc_fn_arg(argoff); 2310 uc_value_t *offset = uc_fn_arg(argoff + 1); 2311 const char *startfrom = NULL; 2312 ssize_t bufrem, size, n; 2313 uc_value_t *result; 2314 formatcode_t *code; 2315 size_t ncode, off; 2316 2317 if (ucv_type(bufval) != UC_STRING) { 2318 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 2319 "Buffer value not a string"); 2320 2321 return NULL; 2322 } 2323 2324 startfrom = ucv_string_get(bufval); 2325 bufrem = ucv_string_length(bufval); 2326 2327 if (offset) { 2328 if (ucv_type(offset) != UC_INTEGER) { 2329 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 2330 "Offset value not an integer"); 2331 2332 return NULL; 2333 } 2334 2335 n = (ssize_t)ucv_int64_get(offset); 2336 2337 if (n < 0) 2338 n += bufrem; 2339 2340 if (n < 0 || n >= bufrem) 2341 return NULL; 2342 2343 startfrom += n; 2344 bufrem -= n; 2345 } 2346 2347 result = ucv_array_new(vm); 2348 2349 for (ncode = 0, code = &state->codes[0], off = 0; 2350 ncode < state->ncodes; 2351 code = &state->codes[++ncode]) { 2352 const formatdef_t *e = code->fmtdef; 2353 const char *res = startfrom + code->offset + off; 2354 ssize_t j = code->repeat; 2355 2356 while (j--) { 2357 uc_value_t *v = NULL; 2358 2359 size = code->size; 2360 2361 if (e->format == '*') { 2362 if (size == -1 || size > bufrem) 2363 size = bufrem; 2364 2365 off += size; 2366 } 2367 else if (size > bufrem) { 2368 goto fail; 2369 } 2370 2371 if (e->format == 's' || e->format == '*') { 2372 v = ucv_string_new_length(res, size); 2373 } 2374 else if (e->format == 'p') { 2375 n = *(unsigned char *)res; 2376 2377 if (n >= size) 2378 n = (size > 0 ? size - 1 : 0); 2379 2380 v = ucv_string_new_length(res + 1, n); 2381 } 2382 else { 2383 v = e->unpack(vm, res, e); 2384 } 2385 2386 if (v == NULL) 2387 goto fail; 2388 2389 ucv_array_push(result, v); 2390 2391 res += size; 2392 bufrem -= size; 2393 } 2394 } 2395 2396 return result; 2397 2398 fail: 2399 ucv_put(result); 2400 2401 return NULL; 2402 } 2403 2404 2405 static uc_value_t * 2406 uc_pack(uc_vm_t *vm, size_t nargs) 2407 { 2408 uc_value_t *fmtval = uc_fn_arg(0); 2409 uc_value_t *res = NULL; 2410 formatstate_t *state; 2411 2412 state = parse_format(vm, fmtval); 2413 2414 if (!state) 2415 return NULL; 2416 2417 res = uc_pack_common(vm, nargs, state, 1); 2418 2419 free(state); 2420 2421 return res; 2422 } 2423 2424 static uc_value_t * 2425 uc_unpack(uc_vm_t *vm, size_t nargs) 2426 { 2427 uc_value_t *fmtval = uc_fn_arg(0); 2428 uc_value_t *res = NULL; 2429 formatstate_t *state; 2430 2431 state = parse_format(vm, fmtval); 2432 2433 if (!state) 2434 return NULL; 2435 2436 res = uc_unpack_common(vm, nargs, state, 1); 2437 2438 free(state); 2439 2440 return res; 2441 } 2442 2443 2444 static uc_value_t * 2445 uc_struct_new(uc_vm_t *vm, size_t nargs) 2446 { 2447 uc_value_t *fmtval = uc_fn_arg(0); 2448 formatstate_t *state; 2449 2450 state = parse_format(vm, fmtval); 2451 2452 if (!state) 2453 return NULL; 2454 2455 return uc_resource_new(struct_type, state); 2456 } 2457 2458 static void 2459 uc_struct_gc(void *ud) 2460 { 2461 formatstate_t *state = ud; 2462 2463 free(state); 2464 } 2465 2466 static uc_value_t * 2467 uc_struct_pack(uc_vm_t *vm, size_t nargs) 2468 { 2469 formatstate_t **state = uc_fn_this("struct"); 2470 2471 if (!state || !*state) 2472 return NULL; 2473 2474 return uc_pack_common(vm, nargs, *state, 0); 2475 } 2476 2477 static uc_value_t * 2478 uc_struct_unpack(uc_vm_t *vm, size_t nargs) 2479 { 2480 formatstate_t **state = uc_fn_this("struct"); 2481 2482 if (!state || !*state) 2483 return NULL; 2484 2485 return uc_unpack_common(vm, nargs, *state, 0); 2486 } 2487 2488 2489 static const uc_function_list_t struct_inst_fns[] = { 2490 { "pack", uc_struct_pack }, 2491 { "unpack", uc_struct_unpack } 2492 }; 2493 2494 static const uc_function_list_t struct_fns[] = { 2495 { "pack", uc_pack }, 2496 { "unpack", uc_unpack }, 2497 { "new", uc_struct_new } 2498 }; 2499 2500 void uc_module_init(uc_vm_t *vm, uc_value_t *scope) 2501 { 2502 optimize_functions(); 2503 2504 uc_function_list_register(scope, struct_fns); 2505 2506 struct_type = uc_type_declare(vm, "struct", struct_inst_fns, uc_struct_gc); 2507 } 2508
This page was automatically generated by LXR 0.3.1. • OpenWrt