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 /** 64 * # Handle Packed Binary Data 65 * 66 * The `struct` module provides routines for interpreting byte strings as packed 67 * binary data. 68 * 69 * Functions can be individually imported and directly accessed using the 70 * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#named_import named import} 71 * syntax: 72 * 73 * ``` 74 * import { pack, unpack } from 'struct'; 75 * 76 * let buffer = pack('bhl', -13, 1234, 444555666); 77 * let values = unpack('bhl', buffer); 78 * ``` 79 * 80 * Alternatively, the module namespace can be imported 81 * using a wildcard import statement: 82 * 83 * ``` 84 * import * as struct from 'struct'; 85 * 86 * let buffer = struct.pack('bhl', -13, 1234, 444555666); 87 * let values = struct.unpack('bhl', buffer); 88 * ``` 89 * 90 * Additionally, the struct module namespace may also be imported by invoking 91 * the `ucode` interpreter with the `-lstruct` switch. 92 * 93 * ## Format Strings 94 * 95 * Format strings describe the data layout when packing and unpacking data. 96 * They are built up from format-characters, which specify the type of data 97 * being packed/unpacked. In addition, special characters control the byte 98 * order, size and alignment. 99 * 100 * Each format string consists of an optional prefix character which describes 101 * the overall properties of the data and one or more format characters which 102 * describe the actual data values and padding. 103 * 104 * ### Byte Order, Size, and Alignment 105 * 106 * By default, C types are represented in the machine's native format and byte 107 * order, and properly aligned by skipping pad bytes if necessary (according to 108 * the rules used by the C compiler). 109 * 110 * This behavior is chosen so that the bytes of a packed struct correspond 111 * exactly to the memory layout of the corresponding C struct. 112 * 113 * Whether to use native byte ordering and padding or standard formats depends 114 * on the application. 115 * 116 * Alternatively, the first character of the format string can be used to indicate 117 * the byte order, size and alignment of the packed data, according to the 118 * following table: 119 * 120 * | Character | Byte order | Size | Alignment | 121 * |-----------|------------------------|----------|-----------| 122 * | `@` | native | native | native | 123 * | `=` | native | standard | none | 124 * | `<` | little-endian | standard | none | 125 * | `>` | big-endian | standard | none | 126 * | `!` | network (= big-endian) | standard | none | 127 * 128 * If the first character is not one of these, `'@'` is assumed. 129 * 130 * Native byte order is big-endian or little-endian, depending on the 131 * host system. For example, Intel x86, AMD64 (x86-64), and Apple M1 are 132 * little-endian; IBM z and many legacy architectures are big-endian. 133 * 134 * Native size and alignment are determined using the C compiler's 135 * `sizeof` expression. This is always combined with native byte order. 136 * 137 * Standard size depends only on the format character; see the table in 138 * the `format-characters` section. 139 * 140 * Note the difference between `'@'` and `'='`: both use native byte order, 141 * but the size and alignment of the latter is standardized. 142 * 143 * The form `'!'` represents the network byte order which is always big-endian 144 * as defined in `IETF RFC 1700`. 145 * 146 * There is no way to indicate non-native byte order (force byte-swapping); use 147 * the appropriate choice of `'<'` or `'>'`. 148 * 149 * Notes: 150 * 151 * (1) Padding is only automatically added between successive structure members. 152 * No padding is added at the beginning or the end of the encoded struct. 153 * 154 * (2) No padding is added when using non-native size and alignment, e.g. 155 * with '<', '>', '=', and '!'. 156 * 157 * (3) To align the end of a structure to the alignment requirement of a 158 * particular type, end the format with the code for that type with a repeat 159 * count of zero. 160 * 161 * 162 * ### Format Characters 163 * 164 * Format characters have the following meaning; the conversion between C and 165 * ucode values should be obvious given their types. The 'Standard size' column 166 * refers to the size of the packed value in bytes when using standard size; 167 * that is, when the format string starts with one of `'<'`, `'>'`, `'!'` or 168 * `'='`. When using native size, the size of the packed value is platform 169 * dependent. 170 * 171 * | Format | C Type | Ucode type | Standard size | Notes | 172 * |--------|----------------------|------------|----------------|----------| 173 * | `x` | *pad byte* | *no value* | | (7) | 174 * | `c` | `char` | string | 1 | | 175 * | `b` | `signed char` | int | 1 | (1), (2) | 176 * | `B` | `unsigned char` | int | 1 | (2) | 177 * | `?` | `_Bool` | bool | 1 | (1) | 178 * | `h` | `short` | int | 2 | (2) | 179 * | `H` | `unsigned short` | int | 2 | (2) | 180 * | `i` | `int` | int | 4 | (2) | 181 * | `I` | `unsigned int` | int | 4 | (2) | 182 * | `l` | `long` | int | 4 | (2) | 183 * | `L` | `unsigned long` | int | 4 | (2) | 184 * | `q` | `long long` | int | 8 | (2) | 185 * | `Q` | `unsigned long long` | int | 8 | (2) | 186 * | `n` | `ssize_t` | int | | (3) | 187 * | `N` | `size_t` | int | | (3) | 188 * | `e` | (6) | double | 2 | (4) | 189 * | `f` | `float` | double | 4 | (4) | 190 * | `d` | `double` | double | 8 | (4) | 191 * | `s` | `char[]` | double | | (9) | 192 * | `p` | `char[]` | double | | (8) | 193 * | `P` | `void *` | int | | (5) | 194 * | `*` | `char[]` | string | | (10) | 195 * | `X` | `char[]` | string | | (11) | 196 * | `Z` | `char[]` | string | | (12) | 197 * 198 * Notes: 199 * 200 * - (1) The `'?'` conversion code corresponds to the `_Bool` type defined by 201 * C99. If this type is not available, it is simulated using a `char`. In 202 * standard mode, it is always represented by one byte. 203 * 204 * - (2) When attempting to pack a non-integer using any of the integer 205 * conversion codes, this module attempts to convert the given value into an 206 * integer. If the value is not convertible, a type error exception is thrown. 207 * 208 * - (3) The `'n'` and `'N'` conversion codes are only available for the native 209 * size (selected as the default or with the `'@'` byte order character). 210 * For the standard size, you can use whichever of the other integer formats 211 * fits your application. 212 * 213 * - (4) For the `'f'`, `'d'` and `'e'` conversion codes, the packed 214 * representation uses the IEEE 754 binary32, binary64 or binary16 format 215 * (for `'f'`, `'d'` or `'e'` respectively), regardless of the floating-point 216 * format used by the platform. 217 * 218 * - (5) The `'P'` format character is only available for the native byte 219 * ordering (selected as the default or with the `'@'` byte order character). 220 * The byte order character `'='` chooses to use little- or big-endian 221 * ordering based on the host system. The struct module does not interpret 222 * this as native ordering, so the `'P'` format is not available. 223 * 224 * - (6) The IEEE 754 binary16 "half precision" type was introduced in the 2008 225 * revision of the `IEEE 754` standard. It has a sign bit, a 5-bit exponent 226 * and 11-bit precision (with 10 bits explicitly stored), and can represent 227 * numbers between approximately `6.1e-05` and `6.5e+04` at full precision. 228 * This type is not widely supported by C compilers: on a typical machine, an 229 * unsigned short can be used for storage, but not for math operations. See 230 * the Wikipedia page on the `half-precision floating-point format` for more 231 * information. 232 * 233 * - (7) When packing, `'x'` inserts one NUL byte. 234 * 235 * - (8) The `'p'` format character encodes a "Pascal string", meaning a short 236 * variable-length string stored in a *fixed number of bytes*, given by the 237 * count. The first byte stored is the length of the string, or 255, 238 * whichever is smaller. The bytes of the string follow. If the string 239 * passed in to `pack()` is too long (longer than the count minus 1), only 240 * the leading `count-1` bytes of the string are stored. If the string is 241 * shorter than `count-1`, it is padded with null bytes so that exactly count 242 * bytes in all are used. Note that for `unpack()`, the `'p'` format 243 * character consumes `count` bytes, but that the string returned can never 244 * contain more than 255 bytes. 245 * 246 * - (9) For the `'s'` format character, the count is interpreted as the length 247 * of the bytes, not a repeat count like for the other format characters; for 248 * example, `'10s'` means a single 10-byte string mapping to or from a single 249 * ucode byte string, while `'10c'` means 10 separate one byte character 250 * elements (e.g., `cccccccccc`) mapping to or from ten different ucode byte 251 * strings. If a count is not given, it defaults to 1. For packing, the 252 * string is truncated or padded with null bytes as appropriate to make it 253 * fit. For unpacking, the resulting bytes object always has exactly the 254 * specified number of bytes. As a special case, `'0s'` means a single, 255 * empty string (while `'0c'` means 0 characters). 256 * 257 * - (10) The `*` format character serves as wildcard. For `pack()` it will 258 * append the corresponding byte argument string as-is, not applying any 259 * padding or zero filling. When a repeat count is given, that many bytes of 260 * the input byte string argument will be appended at most on `pack()`, 261 * effectively truncating longer input strings. For `unpack()`, the wildcard 262 * format will yield a byte string containing the entire remaining input data 263 * bytes, or - when a repeat count is given - that many bytes of input data 264 * at most. 265 * 266 * - (11) The `X` format character handles hexadecimal encoding of binary data. 267 * On `pack()`, the argument is a hexadecimal string; with no repeat count the 268 * entire string is decoded into binary, while a repeat count limits the 269 * number of output bytes (truncating longer input). On `unpack()`, the input 270 * binary data is converted into a hexadecimal string, using all remaining 271 * bytes by default, or at most the specified number of bytes when a repeat 272 * count is given. Decoding accepts both upper- and lowercase hex digits, but 273 * encoding always produces lowercase output. The encoded text length is 274 * exactly twice the number of processed binary bytes. 275 * 276 * - (12) The `Z` format character behaves like `X`, but uses base64 encoding 277 * instead of hexadecimal. On `pack()`, the argument is a base64 string; by 278 * default the entire string is decoded into binary, or at most the specified 279 * number of bytes when a repeat count is given. On `unpack()`, the input 280 * binary data is converted into a base64 string, consuming all remaining 281 * bytes by default, or at most the repeat count if given. The encoded base64 282 * string is approximately 1.4 times the size of the processed binary data. 283 * 284 * A format character may be preceded by an integral repeat count. For example, 285 * the format string `'4h'` means exactly the same as `'hhhh'`. 286 * 287 * Whitespace characters between formats are ignored; a count and its format 288 * must not contain whitespace though. 289 * 290 * When packing a value `x` using one of the integer formats (`'b'`, 291 * `'B'`, `'h'`, `'H'`, `'i'`, `'I'`, `'l'`, `'L'`, 292 * `'q'`, `'Q'`), if `x` is outside the valid range for that format, a type 293 * error exception is raised. 294 * 295 * For the `'?'` format character, the return value is either `true` or `false`. 296 * When packing, the truish result value of the argument is used. Either 0 or 1 297 * in the native or standard bool representation will be packed, and any 298 * non-zero value will be `true` when unpacking. 299 * 300 * ## Examples 301 * 302 * Note: 303 * Native byte order examples (designated by the `'@'` format prefix or 304 * lack of any prefix character) may not match what the reader's 305 * machine produces as 306 * that depends on the platform and compiler. 307 * 308 * Pack and unpack integers of three different sizes, using big endian 309 * ordering: 310 * 311 * ``` 312 * import { pack, unpack } from 'struct'; 313 * 314 * pack(">bhl", 1, 2, 3); // "\x01\x00\x02\x00\x00\x00\x03" 315 * unpack(">bhl", "\x01\x00\x02\x00\x00\x00\x03"); // [ 1, 2, 3 ] 316 * ``` 317 * 318 * Attempt to pack an integer which is too large for the defined field: 319 * 320 * ```bash 321 * $ ucode -lstruct -p 'struct.pack(">h", 99999)' 322 * Type error: Format 'h' requires numeric argument between -32768 and 32767 323 * In [-p argument], line 1, byte 24: 324 * 325 * `struct.pack(">h", 99999)` 326 * Near here -------------^ 327 * ``` 328 * 329 * Demonstrate the difference between `'s'` and `'c'` format characters: 330 * 331 * ``` 332 * import { pack } from 'struct'; 333 * 334 * pack("@ccc", "1", "2", "3"); // "123" 335 * pack("@3s", "123"); // "123" 336 * ``` 337 * 338 * The ordering of format characters may have an impact on size in native 339 * mode since padding is implicit. In standard mode, the user is 340 * responsible for inserting any desired padding. 341 * 342 * Note in the first `pack()` call below that three NUL bytes were added after 343 * the packed `'#'` to align the following integer on a four-byte boundary. 344 * In this example, the output was produced on a little endian machine: 345 * 346 * ``` 347 * import { pack } from 'struct'; 348 * 349 * pack("@ci", "#", 0x12131415); // "#\x00\x00\x00\x15\x14\x13\x12" 350 * pack("@ic", 0x12131415, "#"); // "\x15\x14\x13\x12#" 351 * ``` 352 * 353 * The following format `'ih0i'` results in two pad bytes being added at the 354 * end, assuming the platform's ints are aligned on 4-byte boundaries: 355 * 356 * ``` 357 * import { pack } from 'struct'; 358 * 359 * pack("ih0i", 0x01010101, 0x0202); // "\x01\x01\x01\x01\x02\x02\x00\x00" 360 * ``` 361 * 362 * Use the wildcard format to extract the remainder of the input data: 363 * 364 * ``` 365 * import { unpack } from 'struct'; 366 * 367 * unpack("ccc*", "foobarbaz"); // [ "f", "o", "o", "barbaz" ] 368 * unpack("ccc3*", "foobarbaz"); // [ "f", "o", "o", "bar" ] 369 * ``` 370 * 371 * Use the wildcard format to pack binary stings as-is into the result data: 372 * 373 * ``` 374 * import { pack } from 'struct'; 375 * 376 * pack("h*h", 0x0101, "\x02\x00\x03", 0x0404); // "\x01\x01\x02\x00\x03\x04\x04" 377 * pack("c3*c", "a", "foobar", "c"); // "afooc" 378 * ``` 379 * 380 * @module struct 381 */ 382 383 #include <ctype.h> 384 #include <errno.h> 385 #include <limits.h> 386 #include <math.h> 387 #include <stdlib.h> 388 #include <float.h> 389 #include <assert.h> 390 391 #include "ucode/module.h" 392 #include "ucode/vallist.h" 393 394 typedef struct formatdef { 395 char format; 396 ssize_t size; 397 ssize_t alignment; 398 uc_value_t* (*unpack)(uc_vm_t *, const char *, const struct formatdef *); 399 bool (*pack)(uc_vm_t *, char *, uc_value_t *, const struct formatdef *); 400 } formatdef_t; 401 402 typedef struct { 403 const formatdef_t *fmtdef; 404 ssize_t offset; 405 ssize_t size; 406 ssize_t repeat; 407 } formatcode_t; 408 409 typedef struct { 410 size_t len; 411 size_t size; 412 size_t ncodes; 413 formatcode_t codes[]; 414 } formatstate_t; 415 416 typedef struct { 417 uc_resource_t resource; 418 size_t length; 419 size_t capacity; 420 size_t position; 421 } formatbuffer_t; 422 423 424 /* Define various structs to figure out the alignments of types */ 425 426 typedef struct { char c; short x; } st_short; 427 typedef struct { char c; int x; } st_int; 428 typedef struct { char c; long x; } st_long; 429 typedef struct { char c; float x; } st_float; 430 typedef struct { char c; double x; } st_double; 431 typedef struct { char c; void *x; } st_void_p; 432 typedef struct { char c; size_t x; } st_size_t; 433 typedef struct { char c; bool x; } st_bool; 434 typedef struct { char c; long long x; } s_long_long; 435 436 #define SHORT_ALIGN (sizeof(st_short) - sizeof(short)) 437 #define INT_ALIGN (sizeof(st_int) - sizeof(int)) 438 #define LONG_ALIGN (sizeof(st_long) - sizeof(long)) 439 #define FLOAT_ALIGN (sizeof(st_float) - sizeof(float)) 440 #define DOUBLE_ALIGN (sizeof(st_double) - sizeof(double)) 441 #define VOID_P_ALIGN (sizeof(st_void_p) - sizeof(void *)) 442 #define SIZE_T_ALIGN (sizeof(st_size_t) - sizeof(size_t)) 443 #define BOOL_ALIGN (sizeof(st_bool) - sizeof(bool)) 444 #define LONG_LONG_ALIGN (sizeof(s_long_long) - sizeof(long long)) 445 446 #ifdef __powerc 447 #pragma options align=reset 448 #endif 449 450 451 static bool 452 ucv_as_long(uc_vm_t *vm, uc_value_t *v, long *p) 453 { 454 char *s, *e; 455 int64_t i; 456 double d; 457 long x; 458 459 errno = 0; 460 461 switch (ucv_type(v)) { 462 case UC_INTEGER: 463 i = ucv_int64_get(v); 464 465 if (i < LONG_MIN || i > LONG_MAX) 466 errno = ERANGE; 467 468 x = (long)i; 469 break; 470 471 case UC_DOUBLE: 472 d = ucv_double_get(v); 473 x = (long)d; 474 475 if (isnan(d) || d < (double)LONG_MIN || d > (double)LONG_MAX || d - x != 0) 476 errno = ERANGE; 477 478 break; 479 480 case UC_BOOLEAN: 481 x = (long)ucv_boolean_get(v); 482 break; 483 484 case UC_NULL: 485 x = 0; 486 break; 487 488 case UC_STRING: 489 s = ucv_string_get(v); 490 x = strtol(s, &e, 0); 491 492 if (e == s || *e != '\0') 493 errno = EINVAL; 494 495 break; 496 497 default: 498 errno = EINVAL; 499 x = 0; 500 break; 501 } 502 503 if (errno != 0) { 504 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 505 (errno == ERANGE) 506 ? "Argument out of range" 507 : "Argument not convertible to number"); 508 509 return false; 510 } 511 512 *p = x; 513 514 return true; 515 } 516 517 static bool 518 ucv_as_ulong(uc_vm_t *vm, uc_value_t *v, unsigned long *p) 519 { 520 unsigned long x; 521 char *s, *e; 522 uint64_t i; 523 double d; 524 525 errno = 0; 526 527 switch (ucv_type(v)) { 528 case UC_INTEGER: 529 i = ucv_uint64_get(v); 530 531 if (i > ULONG_MAX) 532 errno = ERANGE; 533 534 x = (unsigned long)i; 535 break; 536 537 case UC_DOUBLE: 538 d = ucv_double_get(v); 539 x = (unsigned long)d; 540 541 if (isnan(d) || d < 0 || d > (double)ULONG_MAX || d - x != 0) 542 errno = ERANGE; 543 544 break; 545 546 case UC_BOOLEAN: 547 x = (unsigned long)ucv_boolean_get(v); 548 break; 549 550 case UC_NULL: 551 x = 0; 552 break; 553 554 case UC_STRING: 555 s = ucv_string_get(v); 556 x = strtoul(s, &e, 0); 557 558 if (e == s || *e != '\0') 559 errno = EINVAL; 560 561 break; 562 563 default: 564 errno = EINVAL; 565 x = 0; 566 break; 567 } 568 569 if (errno != 0) { 570 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 571 (errno == ERANGE) 572 ? "Argument out of range" 573 : "Argument not convertible to number"); 574 575 return false; 576 } 577 578 *p = x; 579 580 return true; 581 } 582 583 static bool 584 ucv_as_longlong(uc_vm_t *vm, uc_value_t *v, long long *p) 585 { 586 char *s, *e; 587 long long x; 588 int64_t i; 589 double d; 590 591 errno = 0; 592 593 switch (ucv_type(v)) { 594 case UC_INTEGER: 595 i = ucv_int64_get(v); 596 597 if (i < LLONG_MIN || i > LLONG_MAX) 598 errno = ERANGE; 599 600 x = (long long)i; 601 break; 602 603 case UC_DOUBLE: 604 d = ucv_double_get(v); 605 x = (long long)d; 606 607 if (isnan(d) || d < (double)LLONG_MIN || d > (double)LLONG_MAX || d - x != 0) 608 errno = ERANGE; 609 610 break; 611 612 case UC_BOOLEAN: 613 x = (long long)ucv_boolean_get(v); 614 break; 615 616 case UC_NULL: 617 x = 0; 618 break; 619 620 case UC_STRING: 621 s = ucv_string_get(v); 622 x = strtoll(s, &e, 0); 623 624 if (e == s || *e != '\0') 625 errno = EINVAL; 626 627 break; 628 629 default: 630 errno = EINVAL; 631 x = 0; 632 break; 633 } 634 635 if (errno != 0) { 636 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 637 (errno == ERANGE) 638 ? "Argument out of range" 639 : "Argument not convertible to number"); 640 641 return false; 642 } 643 644 *p = x; 645 646 return true; 647 } 648 649 static bool 650 ucv_as_ulonglong(uc_vm_t *vm, uc_value_t *v, unsigned long long *p) 651 { 652 unsigned long long x; 653 char *s, *e; 654 uint64_t i; 655 double d; 656 657 errno = 0; 658 659 switch (ucv_type(v)) { 660 case UC_INTEGER: 661 i = ucv_uint64_get(v); 662 663 if (i > ULLONG_MAX) 664 errno = ERANGE; 665 666 x = (unsigned long long)i; 667 break; 668 669 case UC_DOUBLE: 670 d = ucv_double_get(v); 671 x = (unsigned long long)d; 672 673 if (isnan(d) || d < 0 || d > (double)ULLONG_MAX || d - x != 0) 674 errno = ERANGE; 675 676 break; 677 678 case UC_BOOLEAN: 679 x = (unsigned long long)ucv_boolean_get(v); 680 break; 681 682 case UC_NULL: 683 x = 0; 684 break; 685 686 case UC_STRING: 687 s = ucv_string_get(v); 688 x = strtoull(s, &e, 0); 689 690 if (e == s || *e != '\0') 691 errno = EINVAL; 692 693 break; 694 695 default: 696 errno = EINVAL; 697 x = 0; 698 break; 699 } 700 701 if (errno != 0) { 702 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 703 (errno == ERANGE) 704 ? "Argument out of range" 705 : "Argument not convertible to number"); 706 707 return false; 708 } 709 710 *p = x; 711 712 return true; 713 } 714 715 static bool 716 ucv_as_ssize_t(uc_vm_t *vm, uc_value_t *v, ssize_t *p) 717 { 718 char *s, *e; 719 int64_t i; 720 ssize_t x; 721 double d; 722 723 errno = 0; 724 725 switch (ucv_type(v)) { 726 case UC_INTEGER: 727 i = ucv_int64_get(v); 728 729 if (i < -1 || i > SSIZE_MAX) 730 errno = ERANGE; 731 732 x = (ssize_t)i; 733 break; 734 735 case UC_DOUBLE: 736 d = ucv_double_get(v); 737 x = (ssize_t)d; 738 739 if (isnan(d) || d < -1 || d > (double)SSIZE_MAX || d - x != 0) 740 errno = ERANGE; 741 742 break; 743 744 case UC_BOOLEAN: 745 x = (ssize_t)ucv_boolean_get(v); 746 break; 747 748 case UC_NULL: 749 x = 0; 750 break; 751 752 case UC_STRING: 753 s = ucv_string_get(v); 754 i = strtoll(s, &e, 0); 755 756 if (e == s || *e != '\0') 757 errno = EINVAL; 758 else if (i < -1 || i > SSIZE_MAX) 759 errno = ERANGE; 760 761 x = (ssize_t)i; 762 break; 763 764 default: 765 errno = EINVAL; 766 x = 0; 767 break; 768 } 769 770 if (errno != 0) { 771 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 772 (errno == ERANGE) 773 ? "Argument out of range" 774 : "Argument not convertible to number"); 775 776 return false; 777 } 778 779 *p = x; 780 781 return true; 782 } 783 784 /* Same, but handling size_t */ 785 786 static bool 787 ucv_as_size_t(uc_vm_t *vm, uc_value_t *v, size_t *p) 788 { 789 char *s, *e; 790 uint64_t i; 791 double d; 792 size_t x; 793 794 errno = 0; 795 796 switch (ucv_type(v)) { 797 case UC_INTEGER: 798 i = ucv_uint64_get(v); 799 800 if (i > SIZE_MAX) 801 errno = ERANGE; 802 803 x = (size_t)i; 804 break; 805 806 case UC_DOUBLE: 807 d = ucv_double_get(v); 808 x = (size_t)d; 809 810 if (isnan(d) || d < 0 || d > (double)SIZE_MAX || d - x != 0) 811 errno = ERANGE; 812 813 break; 814 815 case UC_BOOLEAN: 816 x = (size_t)ucv_boolean_get(v); 817 break; 818 819 case UC_NULL: 820 x = 0; 821 break; 822 823 case UC_STRING: 824 s = ucv_string_get(v); 825 i = strtoull(s, &e, 0); 826 827 if (e == s || *e != '\0') 828 errno = EINVAL; 829 else if (i > SIZE_MAX) 830 errno = ERANGE; 831 832 x = (size_t)i; 833 break; 834 835 default: 836 errno = EINVAL; 837 x = 0; 838 break; 839 } 840 841 if (errno != 0) { 842 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 843 (errno == ERANGE) 844 ? "Argument out of range" 845 : "Argument not convertible to number"); 846 847 return false; 848 } 849 850 *p = x; 851 852 return true; 853 } 854 855 static bool 856 ucv_as_double(uc_vm_t *vm, uc_value_t *v, double *p) 857 { 858 char *s, *e; 859 int64_t i; 860 double x; 861 862 errno = 0; 863 864 switch (ucv_type(v)) { 865 case UC_INTEGER: 866 i = ucv_int64_get(v); 867 868 if (errno == 0) { 869 if (i < -DBL_MAX || i > DBL_MAX) 870 errno = ERANGE; 871 } 872 873 x = (double)i; 874 break; 875 876 case UC_DOUBLE: 877 x = ucv_double_get(v); 878 break; 879 880 case UC_BOOLEAN: 881 x = (double)ucv_boolean_get(v); 882 break; 883 884 case UC_NULL: 885 x = 0.0; 886 break; 887 888 case UC_STRING: 889 s = ucv_string_get(v); 890 x = strtod(s, &e); 891 892 if (e == s || *e != '\0') 893 errno = EINVAL; 894 895 break; 896 897 default: 898 errno = EINVAL; 899 x = 0.0; 900 break; 901 } 902 903 if (errno != 0) { 904 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 905 (errno == ERANGE) 906 ? "Argument out of range" 907 : "Argument not convertible to number"); 908 909 return false; 910 } 911 912 *p = x; 913 914 return true; 915 } 916 917 918 /* Floating point helpers */ 919 920 static bool 921 double_pack16(double d, char *buf, bool little_endian) 922 { 923 int32_t exponent = 0; 924 uint16_t bits = 0; 925 bool sign = false; 926 double fraction; 927 uint8_t *p; 928 929 if (d == 0.0) { 930 sign = (copysign(1.0, d) == -1.0); 931 } 932 else if (isnan(d)) { 933 sign = (copysign(1.0, d) == -1.0); 934 exponent = 0x1f; 935 bits = 512; 936 } 937 else if (!isfinite(d)) { 938 sign = (d < 0.0); 939 exponent = 0x1f; 940 } 941 else { 942 if (d < 0.0) { 943 sign = true; 944 d = -d; 945 } 946 947 fraction = frexp(d, &exponent); 948 949 assert(fraction >= 0.5 && fraction < 1.0); 950 951 fraction *= 2.0; 952 exponent--; 953 954 if (exponent >= 16) { 955 errno = ERANGE; 956 957 return false; 958 } 959 else if (exponent < -25) { 960 fraction = 0.0; 961 exponent = 0; 962 } 963 else if (exponent < -14) { 964 fraction = ldexp(fraction, 14 + exponent); 965 exponent = 0; 966 } 967 else { 968 fraction -= 1.0; 969 exponent += 15; 970 } 971 972 fraction *= 1024.0; 973 bits = (uint16_t)fraction; 974 975 assert(bits < 1024); 976 assert(exponent < 31); 977 978 if ((fraction - bits > 0.5) || ((fraction - bits == 0.5) && (bits % 2))) { 979 if (++bits == 1024) { 980 bits = 0; 981 982 if (++exponent == 31) { 983 errno = ERANGE; 984 985 return false; 986 } 987 } 988 } 989 } 990 991 bits |= (exponent << 10) | (sign << 15); 992 993 p = (uint8_t *)buf + little_endian; 994 *p = (bits >> 8) & 0xff; 995 996 p += (little_endian ? -1 : 1); 997 *p = bits & 0xff; 998 999 return true; 1000 } 1001 1002 static bool 1003 double_pack32(double d, char *buf, bool little_endian) 1004 { 1005 int8_t step = little_endian ? -1 : 1; 1006 int32_t exponent = 0; 1007 uint32_t bits = 0; 1008 bool sign = false; 1009 double fraction; 1010 uint8_t *p; 1011 1012 if (d == 0.0) { 1013 sign = (copysign(1.0, d) == -1.0); 1014 } 1015 else if (isnan(d)) { 1016 sign = (copysign(1.0, d) == -1.0); 1017 exponent = 0xff; 1018 bits = 0x7fffff; 1019 } 1020 else if (!isfinite(d)) { 1021 sign = (d < 0.0); 1022 exponent = 0xff; 1023 } 1024 else { 1025 if (d < 0.0) { 1026 sign = true; 1027 d = -d; 1028 } 1029 1030 fraction = frexp(d, &exponent); 1031 1032 if (fraction == 0.0) { 1033 exponent = 0; 1034 } 1035 else { 1036 assert(fraction >= 0.5 && fraction < 1.0); 1037 1038 fraction *= 2.0; 1039 exponent--; 1040 } 1041 1042 if (exponent >= 128) { 1043 errno = ERANGE; 1044 1045 return false; 1046 } 1047 else if (exponent < -126) { 1048 fraction = ldexp(fraction, 126 + exponent); 1049 exponent = 0; 1050 } 1051 else if (exponent != 0 || fraction != 0.0) { 1052 fraction -= 1.0; 1053 exponent += 127; 1054 } 1055 1056 fraction *= 8388608.0; 1057 bits = (uint32_t)(fraction + 0.5); 1058 1059 assert(bits <= 8388608); 1060 1061 if (bits >> 23) { 1062 bits = 0; 1063 1064 if (++exponent >= 255) { 1065 errno = ERANGE; 1066 1067 return false; 1068 } 1069 } 1070 } 1071 1072 p = (uint8_t *)buf + (little_endian ? 3 : 0); 1073 *p = (sign << 7) | (exponent >> 1); 1074 1075 p += step; 1076 *p = ((exponent & 1) << 7) | (bits >> 16); 1077 1078 p += step; 1079 *p = (bits >> 8) & 0xff; 1080 1081 p += step; 1082 *p = bits & 0xff; 1083 1084 return true; 1085 } 1086 1087 #define double_pack64 uc_double_pack 1088 1089 static double 1090 double_unpack16(const char *buf, bool little_endian) 1091 { 1092 uint32_t fraction; 1093 int32_t exponent; 1094 uint8_t *p; 1095 bool sign; 1096 double d; 1097 1098 p = (uint8_t *)buf + little_endian; 1099 sign = (*p >> 7) & 1; 1100 exponent = (*p & 0x7c) >> 2; 1101 fraction = (*p & 0x03) << 8; 1102 1103 p += little_endian ? -1 : 1; 1104 fraction |= *p; 1105 1106 if (exponent == 0x1f) { 1107 if (fraction == 0) 1108 return sign ? -INFINITY : INFINITY; 1109 else 1110 return sign ? -NAN : NAN; 1111 } 1112 1113 d = (double)fraction / 1024.0; 1114 1115 if (exponent == 0) { 1116 exponent = -14; 1117 } 1118 else { 1119 exponent -= 15; 1120 d += 1.0; 1121 } 1122 1123 d = ldexp(d, exponent); 1124 1125 return sign ? -d : d; 1126 } 1127 1128 static double 1129 double_unpack32(const char *buf, bool little_endian) 1130 { 1131 int8_t step = little_endian ? -1 : 1; 1132 uint32_t fraction; 1133 int32_t exponent; 1134 uint8_t *p; 1135 bool sign; 1136 double d; 1137 1138 p = (uint8_t *)buf + (little_endian ? 3 : 0); 1139 sign = (*p >> 7) & 1; 1140 exponent = (*p & 0x7f) << 1; 1141 1142 p += step; 1143 exponent |= (*p >> 7) & 1; 1144 fraction = (*p & 0x7f) << 16; 1145 1146 p += step; 1147 fraction |= *p << 8; 1148 1149 p += step; 1150 fraction |= *p; 1151 1152 if (exponent == 0xff) { 1153 if (fraction == 0) 1154 return sign ? -INFINITY : INFINITY; 1155 else 1156 return sign ? -NAN : NAN; 1157 } 1158 1159 d = (double)fraction / 8388608.0; 1160 1161 if (exponent == 0) { 1162 exponent = -126; 1163 } 1164 else { 1165 exponent -= 127; 1166 d += 1.0; 1167 } 1168 1169 d = ldexp(d, exponent); 1170 1171 return sign ? -d : d; 1172 } 1173 1174 #define double_unpack64 uc_double_unpack 1175 1176 static bool 1177 range_exception(uc_vm_t *vm, const formatdef_t *f, bool is_unsigned) 1178 { 1179 /* ulargest is the largest unsigned value with f->size bytes. 1180 * Note that the simpler: 1181 * ((size_t)1 << (f->size * 8)) - 1 1182 * doesn't work when f->size == sizeof(size_t) because C doesn't 1183 * define what happens when a left shift count is >= the number of 1184 * bits in the integer being shifted; e.g., on some boxes it doesn't 1185 * shift at all when they're equal. 1186 */ 1187 const size_t ulargest = (size_t)-1 >> ((sizeof(size_t) - f->size)*8); 1188 1189 assert(f->size >= 1 && f->size <= (ssize_t)sizeof(size_t)); 1190 1191 if (is_unsigned) { 1192 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 1193 "Format '%c' requires numeric argument between 0 and %zu", 1194 f->format, 1195 ulargest); 1196 } 1197 else { 1198 const ssize_t largest = (ssize_t)(ulargest >> 1); 1199 1200 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 1201 "Format '%c' requires numeric argument between %zd and %zd", 1202 f->format, 1203 ~ largest, 1204 largest); 1205 } 1206 1207 return false; 1208 } 1209 1210 1211 /* Native mode routines. ****************************************************/ 1212 1213 static uc_value_t * 1214 native_unpack_char(uc_vm_t *vm, const char *p, const formatdef_t *f) 1215 { 1216 return ucv_string_new_length(p, 1); 1217 } 1218 1219 static uc_value_t * 1220 native_unpack_byte(uc_vm_t *vm, const char *p, const formatdef_t *f) 1221 { 1222 return ucv_int64_new(*(signed char *)p); 1223 } 1224 1225 static uc_value_t * 1226 native_unpack_ubyte(uc_vm_t *vm, const char *p, const formatdef_t *f) 1227 { 1228 return ucv_uint64_new(*(unsigned char *)p); 1229 } 1230 1231 static uc_value_t * 1232 native_unpack_short(uc_vm_t *vm, const char *p, const formatdef_t *f) 1233 { 1234 short x = 0; 1235 1236 memcpy(&x, p, sizeof(x)); 1237 1238 return ucv_int64_new(x); 1239 } 1240 1241 static uc_value_t * 1242 native_unpack_ushort(uc_vm_t *vm, const char *p, const formatdef_t *f) 1243 { 1244 unsigned short x = 0; 1245 1246 memcpy(&x, p, sizeof(x)); 1247 1248 return ucv_uint64_new(x); 1249 } 1250 1251 static uc_value_t * 1252 native_unpack_int(uc_vm_t *vm, const char *p, const formatdef_t *f) 1253 { 1254 int x = 0; 1255 1256 memcpy(&x, p, sizeof(x)); 1257 1258 return ucv_int64_new(x); 1259 } 1260 1261 static uc_value_t * 1262 native_unpack_uint(uc_vm_t *vm, const char *p, const formatdef_t *f) 1263 { 1264 unsigned int x = 0; 1265 1266 memcpy(&x, p, sizeof(x)); 1267 1268 return ucv_uint64_new(x); 1269 } 1270 1271 static uc_value_t * 1272 native_unpack_long(uc_vm_t *vm, const char *p, const formatdef_t *f) 1273 { 1274 long x = 0; 1275 1276 memcpy(&x, p, sizeof(x)); 1277 1278 return ucv_int64_new(x); 1279 } 1280 1281 static uc_value_t * 1282 native_unpack_ulong(uc_vm_t *vm, const char *p, const formatdef_t *f) 1283 { 1284 unsigned long x = 0; 1285 1286 memcpy(&x, p, sizeof(x)); 1287 1288 return ucv_uint64_new(x); 1289 } 1290 1291 static uc_value_t * 1292 native_unpack_ssize_t(uc_vm_t *vm, const char *p, const formatdef_t *f) 1293 { 1294 ssize_t x = 0; 1295 1296 memcpy(&x, p, sizeof(x)); 1297 1298 return ucv_int64_new(x); 1299 } 1300 1301 static uc_value_t * 1302 native_unpack_size_t(uc_vm_t *vm, const char *p, const formatdef_t *f) 1303 { 1304 size_t x = 0; 1305 1306 memcpy(&x, p, sizeof(x)); 1307 1308 return ucv_uint64_new(x); 1309 } 1310 1311 static uc_value_t * 1312 native_unpack_longlong(uc_vm_t *vm, const char *p, const formatdef_t *f) 1313 { 1314 long long x = 0; 1315 1316 memcpy(&x, p, sizeof(x)); 1317 1318 return ucv_int64_new(x); 1319 } 1320 1321 static uc_value_t * 1322 native_unpack_ulonglong(uc_vm_t *vm, const char *p, const formatdef_t *f) 1323 { 1324 unsigned long long x = 0; 1325 1326 memcpy(&x, p, sizeof(x)); 1327 1328 return ucv_uint64_new(x); 1329 } 1330 1331 static uc_value_t * 1332 native_unpack_bool(uc_vm_t *vm, const char *p, const formatdef_t *f) 1333 { 1334 bool x = false; 1335 1336 memcpy(&x, p, sizeof(x)); 1337 1338 return ucv_boolean_new(x != 0); 1339 } 1340 1341 1342 static uc_value_t * 1343 native_unpack_halffloat(uc_vm_t *vm, const char *p, const formatdef_t *f) 1344 { 1345 #if __BYTE_ORDER == __LITTLE_ENDIAN 1346 return ucv_double_new(double_unpack16(p, true)); 1347 #else 1348 return ucv_double_new(double_unpack16(p, false)); 1349 #endif 1350 } 1351 1352 static uc_value_t * 1353 native_unpack_float(uc_vm_t *vm, const char *p, const formatdef_t *f) 1354 { 1355 float x = 0.0; 1356 1357 memcpy(&x, p, sizeof(x)); 1358 1359 return ucv_double_new(x); 1360 } 1361 1362 static uc_value_t * 1363 native_unpack_double(uc_vm_t *vm, const char *p, const formatdef_t *f) 1364 { 1365 double x = 0.0; 1366 1367 memcpy(&x, p, sizeof(x)); 1368 1369 return ucv_double_new(x); 1370 } 1371 1372 static uc_value_t * 1373 native_unpack_void_p(uc_vm_t *vm, const char *p, const formatdef_t *f) 1374 { 1375 void *x = NULL; 1376 1377 memcpy(&x, p, sizeof(x)); 1378 1379 return ucv_int64_new((intptr_t)x); 1380 } 1381 1382 static bool 1383 native_pack_byte(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1384 { 1385 long x = 0; 1386 1387 if (!ucv_as_long(vm, v, &x)) 1388 return false; 1389 1390 if (x < -128 || x > 127) { 1391 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 1392 "Byte format requires numeric value between -128 and 127"); 1393 1394 return false; 1395 } 1396 1397 *p = (char)x; 1398 1399 return true; 1400 } 1401 1402 static bool 1403 native_pack_ubyte(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1404 { 1405 long x = 0; 1406 1407 if (!ucv_as_long(vm, v, &x)) 1408 return false; 1409 1410 if (x < 0 || x > 255) { 1411 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 1412 "Unsigned byte format requires numeric value between 0 and 255"); 1413 1414 return false; 1415 } 1416 1417 *(unsigned char *)p = (unsigned char)x; 1418 1419 return true; 1420 } 1421 1422 static bool 1423 native_pack_char(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1424 { 1425 char *s = NULL; 1426 1427 if (ucv_type(v) == UC_STRING) { 1428 s = ucv_string_get(v); 1429 *p = *s; 1430 } 1431 else { 1432 s = ucv_to_string(vm, v); 1433 *p = *s; 1434 free(s); 1435 } 1436 1437 return true; 1438 } 1439 1440 static bool 1441 native_pack_short(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1442 { 1443 long x = 0; 1444 short y = 0; 1445 1446 if (!ucv_as_long(vm, v, &x)) 1447 return false; 1448 1449 if (x < SHRT_MIN || x > SHRT_MAX) { 1450 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 1451 "Short format requires numeric value between %d and %d", 1452 (int)SHRT_MIN, (int)SHRT_MAX); 1453 1454 return false; 1455 } 1456 1457 y = (short)x; 1458 memcpy(p, &y, sizeof(y)); 1459 1460 return true; 1461 } 1462 1463 static bool 1464 native_pack_ushort(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1465 { 1466 unsigned short y = 0; 1467 long x = 0; 1468 1469 if (!ucv_as_long(vm, v, &x)) 1470 return false; 1471 1472 if (x < 0 || x > USHRT_MAX) { 1473 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 1474 "Unsigned short format requires numeric value between 0 and %u", 1475 (unsigned int)USHRT_MAX); 1476 1477 return false; 1478 } 1479 1480 y = (unsigned short)x; 1481 memcpy(p, &y, sizeof(y)); 1482 1483 return true; 1484 } 1485 1486 static bool 1487 native_pack_int(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1488 { 1489 long x = 0; 1490 int y = 0; 1491 1492 if (!ucv_as_long(vm, v, &x)) 1493 return false; 1494 1495 if (sizeof(long) > sizeof(int)) { 1496 if ((x < ((long)INT_MIN)) || (x > ((long)INT_MAX))) 1497 return range_exception(vm, f, false); 1498 } 1499 1500 y = (int)x; 1501 memcpy(p, &y, sizeof(y)); 1502 1503 return true; 1504 } 1505 1506 static bool 1507 native_pack_uint(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1508 { 1509 unsigned long x = 0; 1510 unsigned int y = 0; 1511 1512 if (!ucv_as_ulong(vm, v, &x)) 1513 return false; 1514 1515 if (sizeof(long) > sizeof(int)) { 1516 if (x > ((unsigned long)UINT_MAX)) 1517 return range_exception(vm, f, true); 1518 } 1519 1520 y = (unsigned int)x; 1521 memcpy(p, &y, sizeof(y)); 1522 1523 return true; 1524 } 1525 1526 static bool 1527 native_pack_long(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1528 { 1529 long x = 0; 1530 1531 if (!ucv_as_long(vm, v, &x)) 1532 return false; 1533 1534 memcpy(p, &x, sizeof(x)); 1535 1536 return true; 1537 } 1538 1539 static bool 1540 native_pack_ulong(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1541 { 1542 unsigned long x = 0; 1543 1544 if (!ucv_as_ulong(vm, v, &x)) 1545 return false; 1546 1547 memcpy(p, &x, sizeof(x)); 1548 1549 return true; 1550 } 1551 1552 static bool 1553 native_pack_ssize_t(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1554 { 1555 ssize_t x = 0; 1556 1557 if (!ucv_as_ssize_t(vm, v, &x)) 1558 return false; 1559 1560 memcpy(p, &x, sizeof(x)); 1561 1562 return true; 1563 } 1564 1565 static bool 1566 native_pack_size_t(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1567 { 1568 size_t x = 0; 1569 1570 if (!ucv_as_size_t(vm, v, &x)) 1571 return false; 1572 1573 memcpy(p, &x, sizeof(x)); 1574 1575 return true; 1576 } 1577 1578 static bool 1579 native_pack_longlong(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1580 { 1581 long long x = 0; 1582 1583 if (!ucv_as_longlong(vm, v, &x)) 1584 return false; 1585 1586 memcpy(p, &x, sizeof(x)); 1587 1588 return true; 1589 } 1590 1591 static bool 1592 native_pack_ulonglong(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1593 { 1594 unsigned long long x = 0; 1595 1596 if (!ucv_as_ulonglong(vm, v, &x)) 1597 return false; 1598 1599 memcpy(p, &x, sizeof(x)); 1600 1601 return true; 1602 } 1603 1604 1605 static bool 1606 native_pack_bool(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1607 { 1608 bool x = 0; 1609 1610 x = ucv_is_truish(v); 1611 1612 memcpy(p, &x, sizeof(x)); 1613 1614 return true; 1615 } 1616 1617 static bool 1618 native_pack_halffloat(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1619 { 1620 double x; 1621 1622 if (!ucv_as_double(vm, v, &x)) 1623 return false; 1624 1625 #if __BYTE_ORDER == __LITTLE_ENDIAN 1626 return double_pack16(x, p, true); 1627 #else 1628 return double_pack16(x, p, false); 1629 #endif 1630 } 1631 1632 static bool 1633 native_pack_float(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1634 { 1635 double d = 0.0; 1636 float x = 0.0; 1637 1638 if (!ucv_as_double(vm, v, &d)) 1639 return false; 1640 1641 x = (float)d; 1642 memcpy(p, &x, sizeof(x)); 1643 1644 return true; 1645 } 1646 1647 static bool 1648 native_pack_double(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1649 { 1650 double x = 0.0; 1651 1652 if (!ucv_as_double(vm, v, &x)) 1653 return false; 1654 1655 memcpy(p, &x, sizeof(x)); 1656 1657 return true; 1658 } 1659 1660 static bool 1661 native_pack_void_p(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1662 { 1663 long long int i = 0; 1664 void *x = NULL; 1665 1666 if (!ucv_as_longlong(vm, v, &i)) 1667 return false; 1668 1669 x = (void *)(intptr_t)i; 1670 memcpy(p, &x, sizeof(x)); 1671 1672 return true; 1673 } 1674 1675 static const formatdef_t native_endian_table[] = { 1676 { 'x', sizeof(char), 0, NULL, NULL }, 1677 { 'b', sizeof(char), 0, native_unpack_byte, native_pack_byte }, 1678 { 'B', sizeof(char), 0, native_unpack_ubyte, native_pack_ubyte }, 1679 { 'c', sizeof(char), 0, native_unpack_char, native_pack_char }, 1680 { '*', sizeof(char), 0, NULL, NULL }, 1681 { 's', sizeof(char), 0, NULL, NULL }, 1682 { 'p', sizeof(char), 0, NULL, NULL }, 1683 { 'X', sizeof(char), 0, NULL, NULL }, 1684 { 'Z', sizeof(char), 0, NULL, NULL }, 1685 { 'h', sizeof(short), SHORT_ALIGN, native_unpack_short, native_pack_short }, 1686 { 'H', sizeof(short), SHORT_ALIGN, native_unpack_ushort, native_pack_ushort }, 1687 { 'i', sizeof(int), INT_ALIGN, native_unpack_int, native_pack_int }, 1688 { 'I', sizeof(int), INT_ALIGN, native_unpack_uint, native_pack_uint }, 1689 { 'l', sizeof(long), LONG_ALIGN, native_unpack_long, native_pack_long }, 1690 { 'L', sizeof(long), LONG_ALIGN, native_unpack_ulong, native_pack_ulong }, 1691 { 'n', sizeof(size_t), SIZE_T_ALIGN, native_unpack_ssize_t, native_pack_ssize_t }, 1692 { 'N', sizeof(size_t), SIZE_T_ALIGN, native_unpack_size_t, native_pack_size_t }, 1693 { 'q', sizeof(long long), LONG_LONG_ALIGN, native_unpack_longlong, native_pack_longlong }, 1694 { 'Q', sizeof(long long), LONG_LONG_ALIGN, native_unpack_ulonglong,native_pack_ulonglong }, 1695 { '?', sizeof(bool), BOOL_ALIGN, native_unpack_bool, native_pack_bool }, 1696 { 'e', sizeof(short), SHORT_ALIGN, native_unpack_halffloat, native_pack_halffloat }, 1697 { 'f', sizeof(float), FLOAT_ALIGN, native_unpack_float, native_pack_float }, 1698 { 'd', sizeof(double), DOUBLE_ALIGN, native_unpack_double, native_pack_double }, 1699 { 'P', sizeof(void *), VOID_P_ALIGN, native_unpack_void_p, native_pack_void_p }, 1700 { 0 } 1701 }; 1702 1703 1704 /* Big-endian routines. *****************************************************/ 1705 1706 static uc_value_t * 1707 be_unpack_int(uc_vm_t *vm, const char *p, const formatdef_t *f) 1708 { 1709 const unsigned char *bytes = (const unsigned char *)p; 1710 ssize_t i = f->size; 1711 long x = 0; 1712 1713 do { 1714 x = (x<<8) | *bytes++; 1715 } while (--i > 0); 1716 1717 /* Extend the sign bit. */ 1718 if ((ssize_t)sizeof(long) > f->size) 1719 x |= -(x & (1L << ((8 * f->size) - 1))); 1720 1721 return ucv_int64_new(x); 1722 } 1723 1724 static uc_value_t * 1725 be_unpack_uint(uc_vm_t *vm, const char *p, const formatdef_t *f) 1726 { 1727 const unsigned char *bytes = (const unsigned char *)p; 1728 ssize_t i = f->size; 1729 unsigned long x = 0; 1730 1731 do { 1732 x = (x<<8) | *bytes++; 1733 } while (--i > 0); 1734 1735 return ucv_uint64_new(x); 1736 } 1737 1738 static uc_value_t * 1739 be_unpack_longlong(uc_vm_t *vm, const char *p, const formatdef_t *f) 1740 { 1741 const unsigned char *bytes = (const unsigned char *)p; 1742 ssize_t i = f->size; 1743 long long x = 0; 1744 1745 do { 1746 x = (x<<8) | *bytes++; 1747 } while (--i > 0); 1748 1749 /* Extend the sign bit. */ 1750 if ((ssize_t)sizeof(long long) > f->size) 1751 x |= -(x & ((long long)1 << ((8 * f->size) - 1))); 1752 1753 return ucv_int64_new(x); 1754 } 1755 1756 static uc_value_t * 1757 be_unpack_ulonglong(uc_vm_t *vm, const char *p, const formatdef_t *f) 1758 { 1759 const unsigned char *bytes = (const unsigned char *)p; 1760 unsigned long long x = 0; 1761 ssize_t i = f->size; 1762 1763 do { 1764 x = (x<<8) | *bytes++; 1765 } while (--i > 0); 1766 1767 return ucv_uint64_new(x); 1768 } 1769 1770 static uc_value_t * 1771 be_unpack_halffloat(uc_vm_t *vm, const char *p, const formatdef_t *f) 1772 { 1773 return ucv_double_new(double_unpack16(p, false)); 1774 } 1775 1776 static uc_value_t * 1777 be_unpack_float(uc_vm_t *vm, const char *p, const formatdef_t *f) 1778 { 1779 return ucv_double_new(double_unpack32(p, false)); 1780 } 1781 1782 static uc_value_t * 1783 be_unpack_double(uc_vm_t *vm, const char *p, const formatdef_t *f) 1784 { 1785 return ucv_double_new(double_unpack64(p, false)); 1786 } 1787 1788 static uc_value_t * 1789 be_unpack_bool(uc_vm_t *vm, const char *p, const formatdef_t *f) 1790 { 1791 return ucv_boolean_new(*p != 0); 1792 } 1793 1794 static bool 1795 be_pack_int(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1796 { 1797 unsigned char *q = (unsigned char *)p; 1798 ssize_t i = 0; 1799 long x = 0; 1800 1801 if (!ucv_as_long(vm, v, &x)) 1802 return false; 1803 1804 i = f->size; 1805 1806 if (i != sizeof(long)) { 1807 if ((i == 2) && (x < -32768 || x > 32767)) 1808 return range_exception(vm, f, false); 1809 #if UINT_MAX < ULONG_MAX 1810 else if ((i == 4) && (x < -2147483648L || x > 2147483647L)) 1811 return range_exception(vm, f, false); 1812 #endif 1813 } 1814 1815 do { 1816 q[--i] = (unsigned char)(x & 0xffL); 1817 x >>= 8; 1818 } while (i > 0); 1819 1820 return true; 1821 } 1822 1823 static bool 1824 be_pack_uint(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1825 { 1826 unsigned char *q = (unsigned char *)p; 1827 unsigned long x = 0; 1828 ssize_t i = 0; 1829 1830 if (!ucv_as_ulong(vm, v, &x)) 1831 return false; 1832 1833 i = f->size; 1834 1835 if (i != sizeof(long)) { 1836 unsigned long maxint = 1; 1837 maxint <<= (unsigned long)(i * 8); 1838 if (x >= maxint) 1839 return range_exception(vm, f, true); 1840 } 1841 1842 do { 1843 q[--i] = (unsigned char)(x & 0xffUL); 1844 x >>= 8; 1845 } while (i > 0); 1846 1847 return true; 1848 } 1849 1850 static bool 1851 be_pack_longlong(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1852 { 1853 unsigned char *q = (unsigned char *)p; 1854 long long x = 0; 1855 ssize_t i = 0; 1856 1857 if (!ucv_as_longlong(vm, v, &x)) 1858 return false; 1859 1860 i = f->size; 1861 1862 do { 1863 q[--i] = (unsigned char)(x & 0xffL); 1864 x >>= 8; 1865 } while (i > 0); 1866 1867 return true; 1868 } 1869 1870 static bool 1871 be_pack_ulonglong(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1872 { 1873 unsigned char *q = (unsigned char *)p; 1874 unsigned long long x = 0; 1875 ssize_t i = 0; 1876 1877 if (!ucv_as_ulonglong(vm, v, &x)) 1878 return false; 1879 1880 i = f->size; 1881 1882 do { 1883 q[--i] = (unsigned char)(x & 0xffUL); 1884 x >>= 8; 1885 } while (i > 0); 1886 1887 return true; 1888 } 1889 1890 static bool 1891 be_pack_halffloat(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1892 { 1893 double x = 0.0; 1894 1895 if (!ucv_as_double(vm, v, &x)) 1896 return false; 1897 1898 return double_pack16(x, p, false); 1899 } 1900 1901 static bool 1902 be_pack_float(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1903 { 1904 double x = 0.0; 1905 1906 if (!ucv_as_double(vm, v, &x)) 1907 return false; 1908 1909 if (!double_pack32(x, p, 0)) { 1910 uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Argument out of range"); 1911 1912 return false; 1913 } 1914 1915 return true; 1916 } 1917 1918 static bool 1919 be_pack_double(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1920 { 1921 double x = 0.0; 1922 1923 if (!ucv_as_double(vm, v, &x)) 1924 return false; 1925 1926 if (!double_pack64(x, p, 0)) { 1927 uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Argument out of range"); 1928 1929 return false; 1930 } 1931 1932 return true; 1933 } 1934 1935 static bool 1936 be_pack_bool(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 1937 { 1938 *p = (char)ucv_is_truish(v); 1939 1940 return true; 1941 } 1942 1943 static formatdef_t big_endian_table[] = { 1944 { 'x', 1, 0, NULL, NULL }, 1945 { 'b', 1, 0, native_unpack_byte, native_pack_byte }, 1946 { 'B', 1, 0, native_unpack_ubyte, native_pack_ubyte }, 1947 { 'c', 1, 0, native_unpack_char, native_pack_char }, 1948 { '*', 1, 0, NULL, NULL }, 1949 { 's', 1, 0, NULL, NULL }, 1950 { 'p', 1, 0, NULL, NULL }, 1951 { 'X', 1, 0, NULL, NULL }, 1952 { 'Z', 1, 0, NULL, NULL }, 1953 { 'h', 2, 0, be_unpack_int, be_pack_int }, 1954 { 'H', 2, 0, be_unpack_uint, be_pack_uint }, 1955 { 'i', 4, 0, be_unpack_int, be_pack_int }, 1956 { 'I', 4, 0, be_unpack_uint, be_pack_uint }, 1957 { 'l', 4, 0, be_unpack_int, be_pack_int }, 1958 { 'L', 4, 0, be_unpack_uint, be_pack_uint }, 1959 { 'q', 8, 0, be_unpack_longlong, be_pack_longlong }, 1960 { 'Q', 8, 0, be_unpack_ulonglong, be_pack_ulonglong }, 1961 { '?', 1, 0, be_unpack_bool, be_pack_bool }, 1962 { 'e', 2, 0, be_unpack_halffloat, be_pack_halffloat }, 1963 { 'f', 4, 0, be_unpack_float, be_pack_float }, 1964 { 'd', 8, 0, be_unpack_double, be_pack_double }, 1965 { 0 } 1966 }; 1967 1968 1969 /* Little-endian routines. *****************************************************/ 1970 1971 static uc_value_t * 1972 le_unpack_int(uc_vm_t *vm, const char *p, const formatdef_t *f) 1973 { 1974 const unsigned char *bytes = (const unsigned char *)p; 1975 ssize_t i = f->size; 1976 long x = 0; 1977 1978 do { 1979 x = (x<<8) | bytes[--i]; 1980 } while (i > 0); 1981 1982 /* Extend the sign bit. */ 1983 if ((ssize_t)sizeof(long) > f->size) 1984 x |= -(x & (1L << ((8 * f->size) - 1))); 1985 1986 return ucv_int64_new(x); 1987 } 1988 1989 static uc_value_t * 1990 le_unpack_uint(uc_vm_t *vm, const char *p, const formatdef_t *f) 1991 { 1992 const unsigned char *bytes = (const unsigned char *)p; 1993 ssize_t i = f->size; 1994 unsigned long x = 0; 1995 1996 do { 1997 x = (x<<8) | bytes[--i]; 1998 } while (i > 0); 1999 2000 return ucv_uint64_new(x); 2001 } 2002 2003 static uc_value_t * 2004 le_unpack_longlong(uc_vm_t *vm, const char *p, const formatdef_t *f) 2005 { 2006 const unsigned char *bytes = (const unsigned char *)p; 2007 ssize_t i = f->size; 2008 long long x = 0; 2009 2010 do { 2011 x = (x<<8) | bytes[--i]; 2012 } while (i > 0); 2013 2014 /* Extend the sign bit. */ 2015 if ((ssize_t)sizeof(long long) > f->size) 2016 x |= -(x & ((long long)1 << ((8 * f->size) - 1))); 2017 2018 return ucv_int64_new(x); 2019 } 2020 2021 static uc_value_t * 2022 le_unpack_ulonglong(uc_vm_t *vm, const char *p, const formatdef_t *f) 2023 { 2024 const unsigned char *bytes = (const unsigned char *)p; 2025 unsigned long long x = 0; 2026 ssize_t i = f->size; 2027 2028 do { 2029 x = (x<<8) | bytes[--i]; 2030 } while (i > 0); 2031 2032 return ucv_uint64_new(x); 2033 } 2034 2035 static uc_value_t * 2036 le_unpack_halffloat(uc_vm_t *vm, const char *p, const formatdef_t *f) 2037 { 2038 return ucv_double_new(double_unpack16(p, true)); 2039 } 2040 2041 static uc_value_t * 2042 le_unpack_float(uc_vm_t *vm, const char *p, const formatdef_t *f) 2043 { 2044 return ucv_double_new(double_unpack32(p, true)); 2045 } 2046 2047 static uc_value_t * 2048 le_unpack_double(uc_vm_t *vm, const char *p, const formatdef_t *f) 2049 { 2050 return ucv_double_new(double_unpack64(p, true)); 2051 } 2052 2053 static bool 2054 le_pack_int(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 2055 { 2056 unsigned char *q = (unsigned char *)p; 2057 ssize_t i = 0; 2058 long x = 0; 2059 2060 if (!ucv_as_long(vm, v, &x)) 2061 return false; 2062 2063 i = f->size; 2064 2065 if (i != sizeof(long)) { 2066 if ((i == 2) && (x < -32768 || x > 32767)) 2067 return range_exception(vm, f, false); 2068 #if UINT_MAX < ULONG_MAX 2069 else if ((i == 4) && (x < -2147483648L || x > 2147483647L)) 2070 return range_exception(vm, f, false); 2071 #endif 2072 } 2073 2074 do { 2075 *q++ = (unsigned char)(x & 0xffL); 2076 x >>= 8; 2077 } while (--i > 0); 2078 2079 return true; 2080 } 2081 2082 static bool 2083 le_pack_uint(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 2084 { 2085 unsigned char *q = (unsigned char *)p; 2086 unsigned long x = 0; 2087 ssize_t i = 0; 2088 2089 if (!ucv_as_ulong(vm, v, &x)) 2090 return false; 2091 2092 i = f->size; 2093 2094 if (i != sizeof(long)) { 2095 unsigned long maxint = 1; 2096 maxint <<= (unsigned long)(i * 8); 2097 2098 if (x >= maxint) 2099 return range_exception(vm, f, true); 2100 } 2101 2102 do { 2103 *q++ = (unsigned char)(x & 0xffUL); 2104 x >>= 8; 2105 } while (--i > 0); 2106 2107 return true; 2108 } 2109 2110 static bool 2111 le_pack_longlong(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 2112 { 2113 unsigned char *q = (unsigned char *)p; 2114 long long x = 0; 2115 ssize_t i = 0; 2116 2117 if (!ucv_as_longlong(vm, v, &x)) 2118 return false; 2119 2120 i = f->size; 2121 2122 do { 2123 *q++ = (unsigned char)(x & 0xffL); 2124 x >>= 8; 2125 } while (--i > 0); 2126 2127 return true; 2128 } 2129 2130 static bool 2131 le_pack_ulonglong(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 2132 { 2133 unsigned char *q = (unsigned char *)p; 2134 unsigned long long x = 0; 2135 ssize_t i = 0; 2136 2137 if (!ucv_as_ulonglong(vm, v, &x)) 2138 return false; 2139 2140 i = f->size; 2141 2142 do { 2143 *q++ = (unsigned char)(x & 0xffUL); 2144 x >>= 8; 2145 } while (--i > 0); 2146 2147 return true; 2148 } 2149 2150 static bool 2151 le_pack_halffloat(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 2152 { 2153 double x = 0.0; 2154 2155 if (!ucv_as_double(vm, v, &x)) 2156 return false; 2157 2158 return double_pack16(x, p, true); 2159 } 2160 2161 static bool 2162 le_pack_float(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 2163 { 2164 double x = 0.0; 2165 2166 if (!ucv_as_double(vm, v, &x)) 2167 return false; 2168 2169 if (!double_pack32(x, p, 1)) { 2170 uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Argument out of range"); 2171 2172 return false; 2173 } 2174 2175 return true; 2176 } 2177 2178 static bool 2179 le_pack_double(uc_vm_t *vm, char *p, uc_value_t *v, const formatdef_t *f) 2180 { 2181 double x = 0.0; 2182 2183 if (!ucv_as_double(vm, v, &x)) 2184 return false; 2185 2186 if (!double_pack64(x, p, 1)) { 2187 uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Argument out of range"); 2188 2189 return false; 2190 } 2191 2192 return true; 2193 } 2194 2195 static formatdef_t little_endian_table[] = { 2196 { 'x', 1, 0, NULL, NULL }, 2197 { 'b', 1, 0, native_unpack_byte, native_pack_byte }, 2198 { 'B', 1, 0, native_unpack_ubyte, native_pack_ubyte }, 2199 { 'c', 1, 0, native_unpack_char, native_pack_char }, 2200 { '*', 1, 0, NULL, NULL }, 2201 { 's', 1, 0, NULL, NULL }, 2202 { 'p', 1, 0, NULL, NULL }, 2203 { 'X', 1, 0, NULL, NULL }, 2204 { 'Z', 1, 0, NULL, NULL }, 2205 { 'h', 2, 0, le_unpack_int, le_pack_int }, 2206 { 'H', 2, 0, le_unpack_uint, le_pack_uint }, 2207 { 'i', 4, 0, le_unpack_int, le_pack_int }, 2208 { 'I', 4, 0, le_unpack_uint, le_pack_uint }, 2209 { 'l', 4, 0, le_unpack_int, le_pack_int }, 2210 { 'L', 4, 0, le_unpack_uint, le_pack_uint }, 2211 { 'q', 8, 0, le_unpack_longlong, le_pack_longlong }, 2212 { 'Q', 8, 0, le_unpack_ulonglong, le_pack_ulonglong }, 2213 { '?', 1, 0, be_unpack_bool, be_pack_bool }, 2214 { 'e', 2, 0, le_unpack_halffloat, le_pack_halffloat }, 2215 { 'f', 4, 0, le_unpack_float, le_pack_float }, 2216 { 'd', 8, 0, le_unpack_double, le_pack_double }, 2217 { 0 } 2218 }; 2219 2220 2221 static const formatdef_t * 2222 select_format_table(const char **pfmt) 2223 { 2224 const char *fmt = (*pfmt)++; /* May be backed out of later */ 2225 2226 switch (*fmt) { 2227 case '<': 2228 return little_endian_table; 2229 2230 case '>': 2231 case '!': /* Network byte order is big-endian */ 2232 return big_endian_table; 2233 2234 case '=': /* Host byte order -- different from native in alignment! */ 2235 #if __BYTE_ORDER == __LITTLE_ENDIAN 2236 return little_endian_table; 2237 #else 2238 return big_endian_table; 2239 #endif 2240 2241 default: 2242 --*pfmt; /* Back out of pointer increment */ 2243 /* Fall through */ 2244 2245 case '@': 2246 return native_endian_table; 2247 } 2248 } 2249 2250 2251 /* Get the table entry for a format code */ 2252 2253 static const formatdef_t * 2254 lookup_table_entry(uc_vm_t *vm, int c, const formatdef_t *table) 2255 { 2256 for (; table->format != '\0'; table++) { 2257 if (table->format == c) { 2258 return table; 2259 } 2260 } 2261 2262 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 2263 "Unrecognized character '%c' in struct format", 2264 c); 2265 2266 return NULL; 2267 } 2268 2269 2270 /* Align a size according to a format code. Return -1 on overflow. */ 2271 2272 static ssize_t 2273 align_for_entry(ssize_t size, const formatdef_t *e) 2274 { 2275 ssize_t extra; 2276 2277 if (e->alignment && size > 0) { 2278 extra = (e->alignment - 1) - (size - 1) % (e->alignment); 2279 2280 if (extra > SSIZE_MAX - size) 2281 return -1; 2282 2283 size += extra; 2284 } 2285 2286 return size; 2287 } 2288 2289 2290 static void 2291 optimize_functions(void) 2292 { 2293 /* Check endian and swap in faster functions */ 2294 const formatdef_t *native = native_endian_table; 2295 formatdef_t *other, *ptr; 2296 2297 #if __BYTE_ORDER == __LITTLE_ENDIAN 2298 other = little_endian_table; 2299 #else 2300 other = big_endian_table; 2301 #endif 2302 2303 /* Scan through the native table, find a matching 2304 entry in the endian table and swap in the 2305 native implementations whenever possible 2306 (64-bit platforms may not have "standard" sizes) */ 2307 while (native->format != '\0' && other->format != '\0') { 2308 ptr = other; 2309 2310 while (ptr->format != '\0') { 2311 if (ptr->format == native->format) { 2312 /* Match faster when formats are 2313 listed in the same order */ 2314 if (ptr == other) 2315 other++; 2316 2317 /* Only use the trick if the 2318 size matches */ 2319 if (ptr->size != native->size) 2320 break; 2321 2322 /* Skip float and double, could be 2323 "unknown" float format */ 2324 if (ptr->format == 'd' || ptr->format == 'f') 2325 break; 2326 2327 /* Skip bool, semantics are different for standard size */ 2328 if (ptr->format == '?') 2329 break; 2330 2331 ptr->pack = native->pack; 2332 ptr->unpack = native->unpack; 2333 break; 2334 } 2335 2336 ptr++; 2337 } 2338 2339 native++; 2340 } 2341 } 2342 2343 static formatstate_t * 2344 parse_format(uc_vm_t *vm, uc_value_t *fmtval) 2345 { 2346 ssize_t size, num, itemsize; 2347 const formatdef_t *e, *f; 2348 const char *fmt, *s; 2349 formatstate_t *state; 2350 formatcode_t *codes; 2351 size_t ncodes; 2352 char c; 2353 2354 if (ucv_type(fmtval) != UC_STRING) { 2355 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 2356 "Format value not a string"); 2357 2358 return NULL; 2359 } 2360 2361 fmt = ucv_string_get(fmtval); 2362 2363 if (strlen(fmt) != ucv_string_length(fmtval)) { 2364 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 2365 "Format string contains embedded null character"); 2366 2367 return NULL; 2368 } 2369 2370 f = select_format_table(&fmt); 2371 2372 s = fmt; 2373 size = 0; 2374 ncodes = 0; 2375 2376 while ((c = *s++) != '\0') { 2377 if (isspace(c)) 2378 continue; 2379 2380 if ('' <= c && c <= '9') { 2381 num = c - ''; 2382 2383 while ('' <= (c = *s++) && c <= '9') { 2384 /* overflow-safe version of 2385 if (num*10 + (c - '') > SSIZE_MAX) { ... } */ 2386 if (num >= SSIZE_MAX / 10 && ( 2387 num > SSIZE_MAX / 10 || 2388 (c - '') > SSIZE_MAX % 10)) 2389 goto overflow; 2390 2391 num = num*10 + (c - ''); 2392 } 2393 2394 if (c == '\0') { 2395 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 2396 "Format string contains repeat count given without format specifier"); 2397 2398 return NULL; 2399 } 2400 } 2401 else if (c == '*' || c == 'X' || c == 'Z') 2402 num = -1; 2403 else 2404 num = 1; 2405 2406 e = lookup_table_entry(vm, c, f); 2407 2408 if (e == NULL) 2409 return NULL; 2410 2411 switch (c) { 2412 case '*': /* fall through */ 2413 case 's': 2414 case 'p': 2415 case 'X': 2416 case 'Z': 2417 ncodes++; 2418 break; 2419 2420 case 'x': 2421 break; 2422 2423 default: 2424 if (num) 2425 ncodes++; 2426 2427 break; 2428 } 2429 2430 itemsize = e->size; 2431 size = align_for_entry(size, e); 2432 2433 if (size == -1) 2434 goto overflow; 2435 2436 /* if (size + num * itemsize > SSIZE_MAX) { ... } */ 2437 if (num > (SSIZE_MAX - size) / itemsize) 2438 goto overflow; 2439 2440 size += (c != '*' && c != 'X' && c != 'Z') ? num * itemsize : 0; 2441 } 2442 2443 /* check for overflow */ 2444 if ((ncodes + 1) > ((size_t)SSIZE_MAX / sizeof(formatcode_t))) { 2445 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, "Out of memory"); 2446 2447 return NULL; 2448 } 2449 2450 state = xalloc(sizeof(*state) + ncodes * sizeof(formatcode_t)); 2451 state->size = size; 2452 state->ncodes = ncodes; 2453 2454 codes = state->codes; 2455 2456 s = fmt; 2457 size = 0; 2458 2459 while ((c = *s++) != '\0') { 2460 if (isspace(c)) 2461 continue; 2462 2463 if ('' <= c && c <= '9') { 2464 num = c - ''; 2465 2466 while ('' <= (c = *s++) && c <= '9') 2467 num = num*10 + (c - ''); 2468 2469 } 2470 else if (c == '*' || c == 'X' || c == 'Z') 2471 num = -1; 2472 else 2473 num = 1; 2474 2475 e = lookup_table_entry(vm, c, f); 2476 2477 if (e == NULL) 2478 continue; 2479 2480 size = align_for_entry(size, e); 2481 2482 if (c == '*' || c == 's' || c == 'p' || c == 'X' || c == 'Z') { 2483 codes->offset = size; 2484 codes->size = num; 2485 codes->fmtdef = e; 2486 codes->repeat = 1; 2487 codes++; 2488 size += (c == 's' || c == 'p') ? num : 0; 2489 } 2490 else if (c == 'x') { 2491 size += num; 2492 } 2493 else if (num) { 2494 codes->offset = size; 2495 codes->size = e->size; 2496 codes->fmtdef = e; 2497 codes->repeat = num; 2498 codes++; 2499 size += e->size * num; 2500 } 2501 } 2502 2503 return state; 2504 2505 overflow: 2506 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, 2507 "Total struct size too long"); 2508 2509 return NULL; 2510 } 2511 2512 static bool 2513 grow_buffer(uc_vm_t *vm, void **buf, size_t *bufsz, size_t length) 2514 { 2515 const size_t overhead = sizeof(uc_string_t) + 1; 2516 2517 if (length > *bufsz) { 2518 size_t old_size = *bufsz; 2519 size_t new_size = (length + 7u) & ~7u; 2520 2521 if (*buf != NULL) { 2522 new_size = *bufsz; 2523 2524 while (length > new_size) { 2525 if (new_size > SIZE_MAX - (new_size >> 1)) { 2526 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, 2527 "Overflow reallocating buffer from %zu to %zu bytes", 2528 *bufsz, length); 2529 2530 return false; 2531 } 2532 2533 new_size += ((new_size >> 1) + 7u) & ~7u; 2534 } 2535 } 2536 2537 char *tmp = realloc(*buf, new_size + overhead); 2538 2539 if (!tmp) { 2540 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, 2541 "Error reallocating buffer to %zu+%zu bytes: %m", 2542 new_size, overhead); 2543 2544 return false; 2545 } 2546 2547 if (*buf) 2548 memset(tmp + overhead + old_size - 1, 0, new_size - old_size + 1); 2549 else 2550 memset(tmp, 0, new_size + overhead); 2551 2552 *buf = tmp; 2553 *bufsz = new_size; 2554 } 2555 2556 return true; 2557 } 2558 2559 /* ------------------------------------------------------------------------- 2560 * The following base64 encoding and decoding routines are taken from 2561 * https://git.openwrt.org/?p=project/libubox.git;a=blob;f=base64.c 2562 * and modified for use in ucode. 2563 * 2564 * Original copyright and license statements below. 2565 */ 2566 2567 /* 2568 * base64 - libubox base64 functions 2569 * 2570 * Copyright (C) 2015 Felix Fietkau <nbd@openwrt.org> 2571 * 2572 * Permission to use, copy, modify, and/or distribute this software for any 2573 * purpose with or without fee is hereby granted, provided that the above 2574 * copyright notice and this permission notice appear in all copies. 2575 * 2576 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 2577 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 2578 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 2579 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 2580 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 2581 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 2582 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 2583 */ 2584 2585 /* $OpenBSD: base64.c,v 1.7 2013/12/31 02:32:56 tedu Exp $ */ 2586 2587 /* 2588 * Copyright (c) 1996 by Internet Software Consortium. 2589 * 2590 * Permission to use, copy, modify, and distribute this software for any 2591 * purpose with or without fee is hereby granted, provided that the above 2592 * copyright notice and this permission notice appear in all copies. 2593 * 2594 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 2595 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 2596 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 2597 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 2598 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 2599 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 2600 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2601 * SOFTWARE. 2602 */ 2603 2604 /* 2605 * Portions Copyright (c) 1995 by International Business Machines, Inc. 2606 * 2607 * International Business Machines, Inc. (hereinafter called IBM) grants 2608 * permission under its copyrights to use, copy, modify, and distribute this 2609 * Software with or without fee, provided that the above copyright notice and 2610 * all paragraphs of this notice appear in all copies, and that the name of IBM 2611 * not be used in connection with the marketing of any product incorporating 2612 * the Software or modifications thereof, without specific, written prior 2613 * permission. 2614 * 2615 * To the extent it has a right to do so, IBM grants an immunity from suit 2616 * under its patents, if any, for the use, sale or manufacture of products to 2617 * the extent that such products are used for performing Domain Name System 2618 * dynamic updates in TCP/IP networks by means of the Software. No immunity is 2619 * granted for any product per se or for any other function of any product. 2620 * 2621 * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, 2622 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 2623 * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, 2624 * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING 2625 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN 2626 * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. 2627 */ 2628 2629 /* skips all whitespace anywhere. 2630 converts characters, four at a time, starting at (or after) 2631 src from base - 64 numbers into three 8 bit bytes in the target area. 2632 it returns the number of data bytes stored at the target, or -1 on error. 2633 */ 2634 2635 static bool 2636 b64dec(char *dest, size_t *dest_len, const char *src, size_t src_len, 2637 const char **errp) 2638 { 2639 enum { BYTE1, BYTE2, BYTE3, BYTE4 } state = BYTE1; 2640 unsigned int ch = 0; 2641 size_t dest_off = 0; 2642 size_t src_off = 0; 2643 uint8_t val; 2644 2645 for (; src_off < src_len; src_off++) { 2646 ch = (unsigned char)src[src_off]; 2647 2648 if (isspace(ch)) /* Skip whitespace anywhere. */ 2649 continue; 2650 2651 if (ch == '=' || dest_off >= *dest_len) 2652 break; 2653 2654 if (ch >= 'A' && ch <= 'Z') 2655 val = ch - 'A'; 2656 else if (ch >= 'a' && ch <= 'z') 2657 val = ch - 'a' + 26; 2658 else if (ch >= '' && ch <= '9') 2659 val = ch - '' + 52; 2660 else if (ch == '+') 2661 val = 62; 2662 else if (ch == '/') 2663 val = 63; 2664 else 2665 return *errp = "Invalid character", false; 2666 2667 switch (state) { 2668 case BYTE1: 2669 dest[dest_off] = val << 2; 2670 state = BYTE2; 2671 break; 2672 2673 case BYTE2: 2674 dest[dest_off++] |= val >> 4; 2675 dest[dest_off] = (val & 0x0f) << 4; 2676 state = BYTE3; 2677 break; 2678 2679 case BYTE3: 2680 dest[dest_off++] |= val >> 2; 2681 dest[dest_off] = (val & 0x03) << 6; 2682 state = BYTE4; 2683 break; 2684 2685 case BYTE4: 2686 dest[dest_off++] |= val; 2687 state = BYTE1; 2688 break; 2689 } 2690 } 2691 2692 /* 2693 * We are done decoding Base-64 chars. Let's see if we ended 2694 * on a byte boundary, and/or with erroneous trailing characters. 2695 */ 2696 2697 if (ch == '=') { /* We got a pad char. */ 2698 if (src_off >= src_len) 2699 return *errp = "Invalid padding", false; 2700 2701 src_off++; /* Skip it, get next. */ 2702 2703 switch (state) { 2704 case BYTE1: /* Invalid = in first position */ 2705 case BYTE2: /* Invalid = in second position */ 2706 return false; 2707 2708 case BYTE3: /* Valid, means one byte of info */ 2709 ch = 0; 2710 2711 while (src_off < src_len) { 2712 ch = (unsigned char)src[src_off]; 2713 2714 if (!isspace(ch)) 2715 break; 2716 } 2717 2718 /* Make sure there is another trailing = sign. */ 2719 if (ch != '=') 2720 return *errp = "Invalid padding", false; 2721 2722 src_off++; /* Skip the = */ 2723 2724 /* Fall through to "single trailing =" case. */ 2725 /* FALLTHROUGH */ 2726 2727 case BYTE4: /* Valid, means two bytes of info */ 2728 /* 2729 * We know this char is an =. Is there anything but 2730 * whitespace after it? 2731 */ 2732 while (src_off < src_len) 2733 if (!isspace(src[src_off])) 2734 return *errp = "Trailing data", false; 2735 2736 /* 2737 * Now make sure for cases BYTE3 and BYTE4 that the "extra" 2738 * bits that slopped past the last full byte were 2739 * zeros. If we don't check them, they become a 2740 * subliminal channel. 2741 */ 2742 if (dest_off < *dest_len && dest[dest_off] != 0) 2743 return *errp = "Extraneous bits", false; 2744 } 2745 } 2746 else { 2747 /* 2748 * We ended by seeing the end of the string. Make sure we 2749 * have no partial bytes lying around. 2750 */ 2751 if (state != BYTE1 && *dest_len == SIZE_MAX) 2752 return *errp = "Input string too long", false; 2753 } 2754 2755 return *dest_len = dest_off, *errp = NULL, true; 2756 } 2757 2758 static const char Base64[] = 2759 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 2760 2761 static size_t 2762 b64len(const char *src, size_t src_len) 2763 { 2764 size_t padding_len = 0; 2765 size_t total_len = 0; 2766 size_t i = 0; 2767 2768 for (; i < src_len; i++) { 2769 if (isspace(src[i])) 2770 continue; 2771 2772 if ((src[i] >= 'A' && src[i] <= 'Z') || 2773 (src[i] >= 'a' && src[i] <= 'z') || 2774 (src[i] >= '' && src[i] <= '9') || 2775 (src[i] == '+') || (src[i] == '/')) 2776 total_len++; 2777 else 2778 break; 2779 } 2780 2781 for (; i < src_len; i++) { 2782 if (isspace(src[i])) 2783 continue; 2784 2785 if (src[i] == '=') 2786 total_len++, padding_len++; 2787 else 2788 return 0; 2789 } 2790 2791 if ((total_len % 4) != 0 || total_len < 4 || padding_len > 2) 2792 return 0; 2793 2794 return (total_len / 4) * 3 - padding_len; 2795 } 2796 2797 static uc_value_t * 2798 b64enc(const char *src, size_t src_len) 2799 { 2800 unsigned char input[3] = {0}; 2801 uc_stringbuf_t *buf; 2802 char output[4]; 2803 size_t i; 2804 2805 buf = ucv_stringbuf_new(); 2806 2807 while (2 < src_len) { 2808 input[0] = (unsigned char)*src++; 2809 input[1] = (unsigned char)*src++; 2810 input[2] = (unsigned char)*src++; 2811 src_len -= 3; 2812 2813 output[0] = Base64[input[0] >> 2]; 2814 output[1] = Base64[((input[0] & 0x03) << 4) + (input[1] >> 4)]; 2815 output[2] = Base64[((input[1] & 0x0f) << 2) + (input[2] >> 6)]; 2816 output[3] = Base64[input[2] & 0x3f]; 2817 2818 ucv_stringbuf_addstr(buf, output, sizeof(output)); 2819 } 2820 2821 /* Now we worry about padding. */ 2822 if (0 != src_len) { 2823 /* Get what's left. */ 2824 input[0] = input[1] = input[2] = '\0'; 2825 for (i = 0; i < src_len; i++) 2826 input[i] = *src++; 2827 2828 output[0] = Base64[input[0] >> 2]; 2829 output[1] = Base64[((input[0] & 0x03) << 4) + (input[1] >> 4)]; 2830 output[2] = (src_len == 1) ? '=' : Base64[((input[1] & 0x0f) << 2) + (input[2] >> 6)]; 2831 output[3] = '='; 2832 2833 ucv_stringbuf_addstr(buf, output, sizeof(output)); 2834 } 2835 2836 return ucv_stringbuf_finish(buf); 2837 } 2838 2839 static bool 2840 uc_pack_common(uc_vm_t *vm, size_t nargs, formatstate_t *state, size_t argoff, 2841 void **buf, size_t *pos, size_t *capacity) 2842 { 2843 size_t ncode, arg, off, new_pos; 2844 formatcode_t *code; 2845 ssize_t size, n; 2846 const void *p; 2847 2848 for (ncode = 0, code = &state->codes[0], arg = argoff, off = 0; 2849 ncode < state->ncodes; 2850 code = &state->codes[++ncode]) { 2851 if (code->fmtdef->format == '*') { 2852 uc_value_t *v = uc_fn_arg(arg++); 2853 2854 if (ucv_type(v) != UC_STRING) 2855 continue; 2856 2857 n = ucv_string_length(v); 2858 2859 if (code->size == -1 || code->size > n) 2860 off += n; 2861 else 2862 off += code->size; 2863 } 2864 else if (code->fmtdef->format == 'X') { 2865 uc_value_t *v = uc_fn_arg(arg++); 2866 2867 if (ucv_type(v) != UC_STRING) 2868 continue; 2869 2870 n = ucv_string_length(v) / 2; 2871 2872 if (code->size == -1 || code->size > n) 2873 off += n; 2874 else 2875 off += code->size; 2876 } 2877 else if (code->fmtdef->format == 'Z') { 2878 uc_value_t *v = uc_fn_arg(arg++); 2879 2880 if (ucv_type(v) != UC_STRING) 2881 continue; 2882 2883 n = b64len(ucv_string_get(v), ucv_string_length(v)); 2884 2885 if (code->size == -1 || code->size > n) 2886 off += n; 2887 else 2888 off += code->size; 2889 } 2890 else { 2891 arg += code->repeat; 2892 } 2893 } 2894 2895 new_pos = *pos + state->size + off; 2896 2897 if (!grow_buffer(vm, buf, capacity, new_pos)) 2898 return NULL; 2899 2900 for (ncode = 0, code = &state->codes[0], off = 0; 2901 ncode < state->ncodes; 2902 code = &state->codes[++ncode]) { 2903 const formatdef_t *e = code->fmtdef; 2904 char *res = *buf + sizeof(uc_string_t) + *pos + code->offset + off; 2905 ssize_t j = code->repeat; 2906 2907 while (j--) { 2908 uc_value_t *v = uc_fn_arg(argoff++); 2909 2910 size = code->size; 2911 2912 if (e->format == '*') { 2913 if (ucv_type(v) != UC_STRING) { 2914 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 2915 "Argument for '*' must be a string"); 2916 2917 return false; 2918 } 2919 2920 n = ucv_string_length(v); 2921 p = ucv_string_get(v); 2922 2923 if (size == -1 || n < size) 2924 size = n; 2925 else if (n > size) 2926 n = size; 2927 2928 off += size; 2929 2930 if (n > 0) 2931 memcpy(res, p, n); 2932 } 2933 else if (e->format == 's') { 2934 if (ucv_type(v) != UC_STRING) { 2935 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 2936 "Argument for 's' must be a string"); 2937 2938 return false; 2939 } 2940 2941 n = ucv_string_length(v); 2942 p = ucv_string_get(v); 2943 2944 if (n > size) 2945 n = size; 2946 2947 if (n > 0) 2948 memcpy(res, p, n); 2949 } 2950 else if (e->format == 'p') { 2951 if (ucv_type(v) != UC_STRING) { 2952 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 2953 "Argument for 'p' must be a string"); 2954 2955 return false; 2956 } 2957 2958 n = ucv_string_length(v); 2959 p = ucv_string_get(v); 2960 2961 if (n > (size - 1)) 2962 n = size - 1; 2963 2964 if (n > 0) 2965 memcpy(res + 1, p, n); 2966 2967 if (n > 255) 2968 n = 255; 2969 2970 *res = (unsigned char)n; 2971 } 2972 else if (e->format == 'X') { 2973 if (ucv_type(v) != UC_STRING) { 2974 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 2975 "Argument for 'X' must be a string"); 2976 2977 return false; 2978 } 2979 2980 n = ucv_string_length(v); 2981 p = ucv_string_get(v); 2982 2983 if (n % 2) { 2984 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 2985 "String length must be multiple of 2"); 2986 2987 return false; 2988 } 2989 2990 if (size == -1 || n / 2 < size) 2991 size = n / 2; 2992 else if (n > size * 2) 2993 n = size * 2; 2994 2995 for (ssize_t i = 0; i < n; i += 2) { 2996 uint8_t c1 = ((uint8_t *)p)[i + 0]; 2997 uint8_t c2 = ((uint8_t *)p)[i + 1]; 2998 2999 if (!isxdigit(c1) || !isxdigit(c2)) { 3000 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 3001 "Invalid hexadecimal string"); 3002 3003 return false; 3004 } 3005 3006 c1 |= 32; c1 = (c1 >= 'a') ? 10 + c1 - 'a' : c1 - ''; 3007 c2 |= 32; c2 = (c2 >= 'a') ? 10 + c2 - 'a' : c2 - ''; 3008 3009 ((uint8_t *)res)[i >> 1] = (c1 << 4) | c2; 3010 } 3011 } 3012 else if (e->format == 'Z') { 3013 if (ucv_type(v) != UC_STRING) { 3014 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 3015 "Argument for 'Z' must be a string"); 3016 3017 return false; 3018 } 3019 3020 n = ucv_string_length(v); 3021 p = ucv_string_get(v); 3022 3023 size_t len = (size == -1) ? SIZE_MAX : (size_t)size; 3024 const char *err = NULL; 3025 3026 if (!b64dec(res, &len, p, n, &err)) { 3027 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 3028 "Invalid base64 string: %s", err); 3029 3030 return false; 3031 } 3032 3033 if (size == -1 || len < (size_t)size) 3034 size = len; 3035 } 3036 else { 3037 if (!e->pack(vm, res, v, e)) 3038 return false; 3039 } 3040 3041 res += size; 3042 } 3043 } 3044 3045 *pos = new_pos; 3046 3047 return true; 3048 } 3049 3050 static uc_value_t * 3051 hexenc(const char *src, size_t src_len) 3052 { 3053 uc_string_t *us = xalloc(sizeof(*us) + src_len * 2 + 1); 3054 const char *hexdigits = "0123456789abcdef"; 3055 3056 us->header.type = UC_STRING; 3057 us->header.refcount = 1; 3058 us->length = src_len * 2; 3059 3060 for (size_t i = 0; i < src_len; i++) { 3061 uint8_t c = (uint8_t)src[i]; 3062 3063 us->str[(i << 1) + 0] = hexdigits[c >> 4]; 3064 us->str[(i << 1) + 1] = hexdigits[c & 0x0f]; 3065 } 3066 3067 return &us->header; 3068 } 3069 3070 static uc_value_t * 3071 uc_unpack_common(uc_vm_t *vm, size_t nargs, formatstate_t *state, 3072 const char *buf, long long pos, size_t *rem, bool single) 3073 { 3074 uc_value_t *result; 3075 formatcode_t *code; 3076 size_t ncode, off; 3077 ssize_t size, n; 3078 3079 if (pos < 0) 3080 pos += *rem; 3081 3082 if (pos < 0 || (size_t)pos >= *rem) 3083 return NULL; 3084 3085 buf += pos; 3086 *rem -= pos; 3087 3088 result = single ? NULL : ucv_array_new(vm); 3089 3090 for (ncode = 0, code = &state->codes[0], off = 0; 3091 ncode < state->ncodes; 3092 code = &state->codes[++ncode]) { 3093 const formatdef_t *e = code->fmtdef; 3094 const char *res = buf + code->offset + off; 3095 ssize_t j = code->repeat; 3096 3097 while (j--) { 3098 uc_value_t *v = NULL; 3099 3100 size = code->size; 3101 3102 if (e->format == '*' || e->format == 'X' || e->format == 'Z') { 3103 if (size == -1 || (size_t)size > *rem) 3104 size = *rem; 3105 3106 off += size; 3107 } 3108 else if (size >= 0 && (size_t)size > *rem) { 3109 goto fail; 3110 } 3111 3112 if (e->format == 's' || e->format == '*') { 3113 v = ucv_string_new_length(res, size); 3114 } 3115 else if (e->format == 'p') { 3116 n = *(unsigned char *)res; 3117 3118 if (n >= size) 3119 n = (size > 0 ? size - 1 : 0); 3120 3121 v = ucv_string_new_length(res + 1, n); 3122 } 3123 else if (e->format == 'X') { 3124 v = hexenc(res, size); 3125 } 3126 else if (e->format == 'Z') { 3127 v = b64enc(res, size); 3128 } 3129 else { 3130 v = e->unpack(vm, res, e); 3131 } 3132 3133 if (v == NULL) 3134 goto fail; 3135 3136 res += size; 3137 *rem -= size; 3138 3139 if (single) 3140 return v; 3141 3142 ucv_array_push(result, v); 3143 } 3144 } 3145 3146 return result; 3147 3148 fail: 3149 ucv_put(result); 3150 3151 return NULL; 3152 } 3153 3154 3155 /** 3156 * Pack given values according to specified format. 3157 * 3158 * The `pack()` function creates a byte string containing the argument values 3159 * packed according to the given format string. 3160 * 3161 * Returns the packed string. 3162 * 3163 * Raises a runtime exception if a given argument value does not match the 3164 * required type of the corresponding format string directive or if and invalid 3165 * format string is provided. 3166 * 3167 * @function module:struct#pack 3168 * 3169 * @param {string} format 3170 * The format string. 3171 * 3172 * @param {...*} values 3173 * Variable number of values to pack. 3174 * 3175 * @returns {string} 3176 * 3177 * @example 3178 * // Pack the values 1, 2, 3 as three consecutive unsigned int values 3179 * // in network byte order. 3180 * const data = pack('!III', 1, 2, 3); 3181 */ 3182 static uc_value_t * 3183 uc_pack(uc_vm_t *vm, size_t nargs) 3184 { 3185 uc_value_t *fmtval = uc_fn_arg(0); 3186 size_t pos = 0, capacity = 0; 3187 uc_string_t *us = NULL; 3188 formatstate_t *state; 3189 3190 state = parse_format(vm, fmtval); 3191 3192 if (!state) 3193 return NULL; 3194 3195 if (!uc_pack_common(vm, nargs, state, 1, (void **)&us, &pos, &capacity)) { 3196 free(state); 3197 free(us); 3198 3199 return NULL; 3200 } 3201 3202 free(state); 3203 3204 us->header.type = UC_STRING; 3205 us->header.refcount = 1; 3206 us->length = pos; 3207 3208 return &us->header; 3209 } 3210 3211 /** 3212 * Unpack given byte string according to specified format. 3213 * 3214 * The `unpack()` function interpretes a byte string according to the given 3215 * format string and returns the resulting values. If the optional offset 3216 * argument is given, unpacking starts from this byte position within the input. 3217 * If not specified, the start offset defaults to `0`, the start of the given 3218 * input string. 3219 * 3220 * Returns an array of unpacked values. 3221 * 3222 * Raises a runtime exception if the format string is invalid or if an invalid 3223 * input string or offset value is given. 3224 * 3225 * @function module:struct#unpack 3226 * 3227 * @param {string} format 3228 * The format string. 3229 * 3230 * @param {string} input 3231 * The input string to unpack. 3232 * 3233 * @param {number} [offset=0] 3234 * The offset within the input string to start unpacking from. 3235 * 3236 * @returns {array} 3237 * 3238 * @example 3239 * // Unpack three consecutive unsigned int values in network byte order. 3240 * const numbers = 3241 * unpack('!III', '\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03'); 3242 * print(numbers, "\n"); // [ 1, 2, 3 ] 3243 */ 3244 static uc_value_t * 3245 uc_unpack(uc_vm_t *vm, size_t nargs) 3246 { 3247 uc_value_t *fmtval = uc_fn_arg(0); 3248 uc_value_t *bufval = uc_fn_arg(1); 3249 uc_value_t *offset = uc_fn_arg(2); 3250 uc_value_t *res = NULL; 3251 formatstate_t *state; 3252 long long pos = 0; 3253 size_t rem; 3254 char *buf; 3255 3256 if (ucv_type(bufval) != UC_STRING) { 3257 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 3258 "Buffer value not a string"); 3259 3260 return NULL; 3261 } 3262 3263 if (offset && !ucv_as_longlong(vm, offset, &pos)) 3264 return NULL; 3265 3266 state = parse_format(vm, fmtval); 3267 3268 if (!state) 3269 return NULL; 3270 3271 buf = ucv_string_get(bufval); 3272 rem = ucv_string_length(bufval); 3273 res = uc_unpack_common(vm, nargs, state, buf, pos, &rem, false); 3274 3275 free(state); 3276 3277 return res; 3278 } 3279 3280 3281 /** 3282 * Represents a struct instance created by `new()`. 3283 * 3284 * @class module:struct.instance 3285 * @hideconstructor 3286 * 3287 * @see {@link module:struct#new|new()} 3288 * 3289 * @example 3290 * 3291 * const fmt = struct.new(…); 3292 * 3293 * fmt.pack(…); 3294 * 3295 * const values = fmt.unpack(…); 3296 */ 3297 3298 /** 3299 * Precompile format string. 3300 * 3301 * The `new()` function precompiles the given format string argument and returns 3302 * a `struct` object instance useful for packing and unpacking multiple items 3303 * without having to recompute the internal format each time. 3304 * 3305 * Returns an precompiled struct format instance. 3306 * 3307 * Raises a runtime exception if the format string is invalid. 3308 * 3309 * @function module:struct#new 3310 * 3311 * @param {string} format 3312 * The format string. 3313 * 3314 * @returns {module:struct.instance} 3315 * 3316 * @example 3317 * // Create a format of three consecutive unsigned int values in network byte order. 3318 * const fmt = struct.new('!III'); 3319 * const buf = fmt.pack(1, 2, 3); // "\x00\x00\x00\x01…" 3320 * print(fmt.unpack(buf), "\n"); // [ 1, 2, 3 ] 3321 */ 3322 static uc_value_t * 3323 uc_struct_new(uc_vm_t *vm, size_t nargs) 3324 { 3325 uc_value_t *fmtval = uc_fn_arg(0); 3326 formatstate_t *state; 3327 3328 state = parse_format(vm, fmtval); 3329 3330 if (!state) 3331 return NULL; 3332 3333 return ucv_resource_create(vm, "struct.format", state); 3334 } 3335 3336 /** 3337 * Pack given values. 3338 * 3339 * The `pack()` function creates a byte string containing the argument values 3340 * packed according to the given format instance. 3341 * 3342 * Returns the packed string. 3343 * 3344 * Raises a runtime exception if a given argument value does not match the 3345 * required type of the corresponding format string directive. 3346 * 3347 * @function module:struct.instance#pack 3348 * 3349 * @param {...*} values 3350 * Variable number of values to pack. 3351 * 3352 * @returns {string} 3353 * 3354 * @example 3355 * const fmt = struct.new(…); 3356 * const data = fmt.pack(…); 3357 */ 3358 static uc_value_t * 3359 uc_struct_pack(uc_vm_t *vm, size_t nargs) 3360 { 3361 formatstate_t **state = uc_fn_this("struct.format"); 3362 size_t pos = 0, capacity = 0; 3363 uc_string_t *us = NULL; 3364 3365 if (!state || !*state) 3366 return NULL; 3367 3368 if (!uc_pack_common(vm, nargs, *state, 0, (void **)&us, &pos, &capacity)) { 3369 free(us); 3370 3371 return NULL; 3372 } 3373 3374 us->header.type = UC_STRING; 3375 us->header.refcount = 1; 3376 us->length = pos; 3377 3378 return &us->header; 3379 } 3380 3381 /** 3382 * Unpack given byte string. 3383 * 3384 * The `unpack()` function interpretes a byte string according to the given 3385 * format instance and returns the resulting values. If the optional offset 3386 * argument is given, unpacking starts from this byte position within the input. 3387 * If not specified, the start offset defaults to `0`, the start of the given 3388 * input string. 3389 * 3390 * Returns an array of unpacked values. 3391 * 3392 * Raises a runtime exception if an invalid input string or offset value is 3393 * given. 3394 * 3395 * @function module:struct.instance#unpack 3396 * 3397 * @param {string} input 3398 * The input string to unpack. 3399 * 3400 * @param {number} [offset=0] 3401 * The offset within the input string to start unpacking from. 3402 * 3403 * @returns {array} 3404 * 3405 * @example 3406 * const fmt = struct.new(…); 3407 * const values = fmt.unpack(…); 3408 */ 3409 static uc_value_t * 3410 uc_struct_unpack(uc_vm_t *vm, size_t nargs) 3411 { 3412 formatstate_t **state = uc_fn_this("struct.format"); 3413 uc_value_t *bufval = uc_fn_arg(0); 3414 uc_value_t *offset = uc_fn_arg(1); 3415 long long pos = 0; 3416 size_t rem; 3417 char *buf; 3418 3419 if (!state || !*state) 3420 return NULL; 3421 3422 if (ucv_type(bufval) != UC_STRING) { 3423 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 3424 "Buffer value not a string"); 3425 3426 return NULL; 3427 } 3428 3429 if (offset && !ucv_as_longlong(vm, offset, &pos)) 3430 return NULL; 3431 3432 buf = ucv_string_get(bufval); 3433 rem = ucv_string_length(bufval); 3434 3435 return uc_unpack_common(vm, nargs, *state, buf, pos, &rem, false); 3436 } 3437 3438 3439 /** 3440 * Represents a struct buffer instance created by `buffer()`. 3441 * 3442 * @class module:struct.buffer 3443 * @hideconstructor 3444 * 3445 * @see {@link module:struct#buffer|buffer()} 3446 * 3447 * @example 3448 * 3449 * const buf = struct.buffer(); 3450 * 3451 * buf.put('I', 12345); 3452 * 3453 * const value = buf.get('I'); 3454 */ 3455 3456 /** 3457 * Creates a new struct buffer instance. 3458 * 3459 * The `buffer()` function creates a new struct buffer object that can be used 3460 * for incremental packing and unpacking of binary data. If an initial data 3461 * string is provided, the buffer is initialized with this content. 3462 * 3463 * Note that even when initial data is provided, the buffer position is always 3464 * set to zero. This design assumes that the primary intent when initializing 3465 * a buffer with data is to read (unpack) from the beginning. If you want to 3466 * append data to a pre-initialized buffer, you need to explicitly move the 3467 * position to the end, either by calling `end()` or by setting the position 3468 * manually with `pos()`. 3469 * 3470 * Returns a new struct buffer instance. 3471 * 3472 * @function module:struct#buffer 3473 * 3474 * @param {string} [initialData] 3475 * Optional initial data to populate the buffer with. 3476 * 3477 * @returns {module:struct.buffer} 3478 * 3479 * @example 3480 * // Create an empty buffer 3481 * const emptyBuf = struct.buffer(); 3482 * 3483 * // Create a buffer with initial data 3484 * const dataBuf = struct.buffer("\x01\x02\x03\x04"); 3485 * 3486 * // Read from the beginning of the initialized buffer 3487 * const value = dataBuf.get('I'); 3488 * 3489 * // Append data to the initialized buffer 3490 * dataBuf.end().put('I', 5678); 3491 * 3492 * // Alternative chained syntax for initializing and appending 3493 * const buf = struct.buffer("\x01\x02\x03\x04").end().put('I', 5678); 3494 */ 3495 static uc_value_t * 3496 uc_fmtbuf_new(uc_vm_t *vm, size_t nargs) 3497 { 3498 formatbuffer_t *buffer = xalloc(sizeof(*buffer)); 3499 uc_value_t *init_data = uc_fn_arg(0); 3500 3501 buffer->resource.header.type = UC_RESOURCE; 3502 buffer->resource.header.refcount = 1; 3503 buffer->resource.type = ucv_resource_type_lookup(vm, "struct.buffer"); 3504 3505 if (ucv_type(init_data) == UC_STRING) { 3506 char *buf = ucv_string_get(init_data); 3507 size_t len = ucv_string_length(init_data); 3508 3509 if (!grow_buffer(vm, &buffer->resource.data, &buffer->capacity, len)) { 3510 free(buffer); 3511 3512 return NULL; 3513 } 3514 3515 buffer->length = len; 3516 memcpy((char *)buffer->resource.data + sizeof(uc_string_t), buf, len); 3517 } 3518 3519 return &buffer->resource.header; 3520 } 3521 3522 static formatbuffer_t * 3523 formatbuffer_ctx(uc_vm_t *vm) 3524 { 3525 uc_value_t *ctx = vm->callframes.entries[vm->callframes.count - 1].ctx; 3526 3527 if (ucv_type(ctx) != UC_RESOURCE) 3528 return NULL; 3529 3530 uc_resource_t *res = (uc_resource_t *)ctx; 3531 3532 if (!res->type || strcmp(res->type->name, "struct.buffer") != 0) 3533 return NULL; 3534 3535 return (formatbuffer_t *)res; 3536 } 3537 3538 /** 3539 * Get or set the current position in the buffer. 3540 * 3541 * If called without arguments, returns the current position. 3542 * If called with a position argument, sets the current position to that value. 3543 * 3544 * @function module:struct.buffer#pos 3545 * 3546 * @param {number} [position] 3547 * The position to set. If omitted, the current position is returned. 3548 * 3549 * @returns {number|module:struct.buffer} 3550 * If called without arguments, returns the current position. 3551 * If called with a position argument, returns the buffer instance for chaining. 3552 * 3553 * @example 3554 * const currentPos = buf.pos(); 3555 * buf.pos(10); // Set position to 10 3556 */ 3557 static uc_value_t * 3558 uc_fmtbuf_pos(uc_vm_t *vm, size_t nargs) 3559 { 3560 formatbuffer_t *buffer = formatbuffer_ctx(vm); 3561 uc_value_t *new_pos = uc_fn_arg(0); 3562 3563 if (!buffer) 3564 return NULL; 3565 3566 if (new_pos) { 3567 long long pos; 3568 3569 if (!ucv_as_longlong(vm, new_pos, &pos)) 3570 return NULL; 3571 3572 if (pos < 0) pos += buffer->length; 3573 if (pos < 0) pos = 0; 3574 3575 if (!grow_buffer(vm, &buffer->resource.data, &buffer->capacity, pos)) 3576 return NULL; 3577 3578 buffer->position = pos; 3579 3580 if (buffer->position > buffer->length) 3581 buffer->length = buffer->position; 3582 3583 return ucv_get(&buffer->resource.header); 3584 } 3585 3586 return ucv_uint64_new(buffer->position); 3587 } 3588 3589 /** 3590 * Get or set the current buffer length. 3591 * 3592 * If called without arguments, returns the current length of the buffer. 3593 * If called with a length argument, sets the buffer length to that value, 3594 * padding the data with trailing zero bytes or truncating it depending on 3595 * whether the updated length is larger or smaller than the current length 3596 * respectively. 3597 * 3598 * In case the updated length is smaller than the current buffer offset, the 3599 * position is updated accordingly, so that it points to the new end of the 3600 * truncated buffer data. 3601 * 3602 * @function module:struct.buffer#length 3603 * 3604 * @param {number} [length] 3605 * The length to set. If omitted, the current length is returned. 3606 * 3607 * @returns {number|module:struct.buffer} 3608 * If called without arguments, returns the current length. 3609 * If called with a length argument, returns the buffer instance for chaining. 3610 * 3611 * @example 3612 * const buf = struct.buffer("abc"); // Initialize buffer with three bytes 3613 * const currentLen = buf.length(); // Returns 3 3614 * 3615 * buf.length(6); // Extend to 6 bytes 3616 * buf.slice(); // Trailing null bytes: "abc\x00\x00\x00" 3617 * 3618 * buf.length(2); // Truncate to 2 bytes 3619 * buf.slice(); // Truncated data: "ab" 3620 */ 3621 static uc_value_t * 3622 uc_fmtbuf_length(uc_vm_t *vm, size_t nargs) 3623 { 3624 formatbuffer_t *buffer = formatbuffer_ctx(vm); 3625 uc_value_t *new_len = uc_fn_arg(0); 3626 3627 if (!buffer) 3628 return NULL; 3629 3630 if (new_len) { 3631 size_t len; 3632 3633 if (!ucv_as_size_t(vm, new_len, &len)) 3634 return NULL; 3635 3636 if (len > buffer->length) { 3637 if (!grow_buffer(vm, &buffer->resource.data, &buffer->capacity, len)) 3638 return NULL; 3639 3640 buffer->length = len; 3641 } 3642 else if (len < buffer->length) { 3643 memset((char *)buffer->resource.data + sizeof(uc_string_t) + len, 3644 0, buffer->length - len); 3645 3646 buffer->length = len; 3647 3648 if (len < buffer->position) 3649 buffer->position = len; 3650 } 3651 3652 return ucv_get(&buffer->resource.header); 3653 } 3654 3655 return ucv_uint64_new(buffer->length); 3656 } 3657 3658 /** 3659 * Set the buffer position to the start (0). 3660 * 3661 * @function module:struct.buffer#start 3662 * 3663 * @returns {module:struct.buffer} 3664 * The buffer instance. 3665 * 3666 * @example 3667 * buf.start(); 3668 */ 3669 static uc_value_t * 3670 uc_fmtbuf_start(uc_vm_t *vm, size_t nargs) 3671 { 3672 formatbuffer_t *buffer = formatbuffer_ctx(vm); 3673 3674 if (!buffer) 3675 return NULL; 3676 3677 buffer->position = 0; 3678 3679 return ucv_get(&buffer->resource.header); 3680 } 3681 3682 /** 3683 * Set the buffer position to the end. 3684 * 3685 * @function module:struct.buffer#end 3686 * 3687 * @returns {module:struct.buffer} 3688 * The buffer instance. 3689 * 3690 * @example 3691 * buf.end(); 3692 */ 3693 static uc_value_t * 3694 uc_fmtbuf_end(uc_vm_t *vm, size_t nargs) 3695 { 3696 formatbuffer_t *buffer = formatbuffer_ctx(vm); 3697 3698 if (!buffer) 3699 return NULL; 3700 3701 buffer->position = buffer->length; 3702 3703 return ucv_get(&buffer->resource.header); 3704 } 3705 3706 /** 3707 * Pack data into the buffer at the current position. 3708 * 3709 * The `put()` function packs the given values into the buffer according to 3710 * the specified format string, starting at the current buffer position. 3711 * The format string follows the same syntax as used in `struct.pack()`. 3712 * 3713 * For a detailed explanation of the format string syntax, refer to the 3714 * ["Format Strings" section]{@link module:struct} in the module 3715 * documentation. 3716 * 3717 * @function module:struct.buffer#put 3718 * 3719 * @param {string} format 3720 * The format string specifying how to pack the data. 3721 * 3722 * @param {...*} values 3723 * The values to pack into the buffer. 3724 * 3725 * @returns {module:struct.buffer} 3726 * The buffer instance. 3727 * 3728 * @see {@link module:struct#pack|struct.pack()} 3729 * 3730 * @example 3731 * buf.put('II', 1234, 5678); 3732 */ 3733 static uc_value_t * 3734 uc_fmtbuf_put(uc_vm_t *vm, size_t nargs) 3735 { 3736 formatbuffer_t *buffer = formatbuffer_ctx(vm); 3737 uc_value_t *fmt = uc_fn_arg(0); 3738 formatstate_t *state; 3739 bool res; 3740 3741 if (!buffer) 3742 return NULL; 3743 3744 state = parse_format(vm, fmt); 3745 3746 if (!state) 3747 return NULL; 3748 3749 res = uc_pack_common(vm, nargs, state, 1, 3750 &buffer->resource.data, &buffer->position, &buffer->capacity); 3751 3752 free(state); 3753 3754 if (!res) 3755 return NULL; 3756 3757 if (buffer->position > buffer->length) 3758 buffer->length = buffer->position; 3759 3760 return ucv_get(&buffer->resource.header); 3761 } 3762 3763 static uc_value_t * 3764 fmtbuf_get_common(uc_vm_t *vm, size_t nargs, bool single) 3765 { 3766 formatbuffer_t *buffer = formatbuffer_ctx(vm); 3767 uc_value_t *fmt = uc_fn_arg(0); 3768 formatstate_t *state; 3769 uc_value_t *result; 3770 size_t rem; 3771 char *buf; 3772 3773 if (!buffer) 3774 return NULL; 3775 3776 if (single && ucv_type(fmt) == UC_INTEGER) { 3777 int64_t len = ucv_int64_get(fmt); 3778 3779 if (errno != 0) 3780 goto ebounds; 3781 3782 size_t spos, epos; 3783 3784 if (len < 0) { 3785 if (len == INT64_MIN) 3786 goto ebounds; 3787 3788 if ((uint64_t)-len > buffer->position) 3789 return NULL; 3790 3791 spos = buffer->position + len; 3792 epos = buffer->position; 3793 } 3794 else { 3795 if ((uint64_t)len > (SIZE_MAX - buffer->position)) 3796 goto ebounds; 3797 3798 if (buffer->position + len > buffer->length) 3799 return NULL; 3800 3801 spos = buffer->position; 3802 epos = buffer->position + len; 3803 3804 buffer->position = epos; 3805 } 3806 3807 return ucv_string_new_length( 3808 (char *)buffer->resource.data + sizeof(uc_string_t) + spos, 3809 epos - spos); 3810 3811 ebounds: 3812 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, 3813 "Length value out of bounds"); 3814 3815 return NULL; 3816 } 3817 3818 state = parse_format(vm, fmt); 3819 3820 if (!state) 3821 return NULL; 3822 3823 if (single && (state->ncodes != 1 || state->codes[0].repeat != 1)) { 3824 free(state); 3825 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 3826 "get() expects a format string for a single value. " 3827 "Use read() for multiple values."); 3828 3829 return NULL; 3830 } 3831 3832 rem = buffer->length; 3833 buf = (char *)buffer->resource.data + sizeof(uc_string_t); 3834 3835 result = uc_unpack_common(vm, nargs, state, 3836 buf, buffer->position, &rem, single); 3837 3838 if (result) 3839 buffer->position = buffer->length - rem; 3840 3841 free(state); 3842 3843 return result; 3844 } 3845 3846 /** 3847 * Unpack a single value from the buffer at the current position. 3848 * 3849 * The `get()` function unpacks a single value from the buffer according to the 3850 * specified format string, starting at the current buffer position. 3851 * The format string follows the same syntax as used in `struct.unpack()`. 3852 * 3853 * For a detailed explanation of the format string syntax, refer to the 3854 * ["Format Strings" section]{@link module:struct} in the module documentation. 3855 * 3856 * Alternatively, `get()` accepts a postive or negative integer as format, which 3857 * specifies the length of a string to unpack before or after the current 3858 * position. Negative values extract that many bytes before the current offset 3859 * while postive ones extracts that many bytes after. 3860 * 3861 * @function module:struct.buffer#get 3862 * 3863 * @param {string|number} format 3864 * The format string specifying how to unpack the data. 3865 * 3866 * @returns {*} 3867 * The unpacked value. 3868 * 3869 * @see {@link module:struct#unpack|struct.unpack()} 3870 * 3871 * @example 3872 * const val = buf.get('I'); 3873 * const str = buf.get(5); // equivalent to buf.get('5s') 3874 * const str = buf.get(-3); // equivalent to buf.pos(buf.pos() - 3).get('3s') 3875 */ 3876 static uc_value_t * 3877 uc_fmtbuf_get(uc_vm_t *vm, size_t nargs) 3878 { 3879 return fmtbuf_get_common(vm, nargs, true); 3880 } 3881 3882 /** 3883 * Unpack multiple values from the buffer at the current position. 3884 * 3885 * The `read()` function unpacks multiple values from the buffer according to 3886 * the specified format string, starting at the current buffer position. 3887 * The format string follows the same syntax as used in `struct.unpack()`. 3888 * 3889 * For a detailed explanation of the format string syntax, refer to the 3890 * ["Format Strings" section]{@link module:struct} in the module documentation. 3891 * 3892 * @function module:struct.buffer#get 3893 * 3894 * @param {string} format 3895 * The format string specifying how to unpack the data. 3896 * 3897 * @returns {array} 3898 * An array containing the unpacked values. 3899 * 3900 * @see {@link module:struct#unpack|struct.unpack()} 3901 * 3902 * @example 3903 * const values = buf.get('II'); 3904 */ 3905 static uc_value_t * 3906 uc_fmtbuf_read(uc_vm_t *vm, size_t nargs) 3907 { 3908 return fmtbuf_get_common(vm, nargs, false); 3909 } 3910 3911 /** 3912 * Extract a slice of the buffer content. 3913 * 3914 * The `slice()` function returns a substring of the buffer content 3915 * between the specified start and end positions. 3916 * 3917 * Both the start and end position values may be negative, in which case they're 3918 * relative to the end of the buffer, e.g. `slice(-3)` will extract the last 3919 * three bytes of data. 3920 * 3921 * @function module:struct.buffer#slice 3922 * 3923 * @param {number} [start=0] 3924 * The starting position of the slice. 3925 * 3926 * @param {number} [end=buffer.length()] 3927 * The ending position of the slice (exclusive). 3928 * 3929 * @returns {string} 3930 * A string containing the specified slice of the buffer content. 3931 * 3932 * @example 3933 * const slice = buf.slice(4, 8); 3934 */ 3935 static uc_value_t * 3936 uc_fmtbuf_slice(uc_vm_t *vm, size_t nargs) 3937 { 3938 formatbuffer_t *buffer = formatbuffer_ctx(vm); 3939 uc_value_t *from = uc_fn_arg(0); 3940 uc_value_t *to = uc_fn_arg(1); 3941 long long spos, epos; 3942 char *buf; 3943 3944 if (!buffer) 3945 return NULL; 3946 3947 spos = 0; 3948 epos = buffer->length; 3949 3950 if (from && !ucv_as_longlong(vm, from, &spos)) 3951 return NULL; 3952 3953 if (to && !ucv_as_longlong(vm, to, &epos)) 3954 return NULL; 3955 3956 if (spos < 0) spos += buffer->length; 3957 if (spos < 0) spos = 0; 3958 if ((unsigned long long)spos > buffer->length) spos = buffer->length; 3959 3960 if (epos < 0) epos += buffer->length; 3961 if (epos < spos) epos = spos; 3962 if ((unsigned long long)epos > buffer->length) epos = buffer->length; 3963 3964 buf = (char *)buffer->resource.data + sizeof(uc_string_t) + spos; 3965 3966 return ucv_string_new_length(buf, epos - spos); 3967 } 3968 3969 /** 3970 * Set a slice of the buffer content to given byte value. 3971 * 3972 * The `set()` function overwrites a substring of the buffer content with the 3973 * given byte value, similar to the C `memset()` function, between the specified 3974 * start and end positions. 3975 * 3976 * Both the start and end position values may be negative, in which case they're 3977 * relative to the end of the buffer, e.g. `set(0, -2)` will overwrite the last 3978 * two bytes of data with `\x00`. 3979 * 3980 * When the start or end positions are beyond the current buffer length, the 3981 * buffer is grown accordingly. 3982 * 3983 * @function module:struct.buffer#set 3984 * 3985 * @param {number|string} [value=0] 3986 * The byte value to use when overwriting buffer contents. When a string is 3987 * given, the first character is used as value. 3988 * 3989 * @param {number} [start=0] 3990 * The position to start overwriting from. 3991 * 3992 * @param {number} [end=buffer.length()] 3993 * The position to end overwriting (exclusive). 3994 * 3995 * @returns {module:struct.buffer} 3996 * The buffer instance. 3997 * 3998 * @example 3999 * const buf = struct.buffer("abcde"); 4000 * buf.set("X", 2, 4).slice(); // Buffer content is now "abXXe" 4001 * buf.set().slice(); // Buffer content is now "\x00\x00\x00\x00\x00" 4002 */ 4003 static uc_value_t * 4004 uc_fmtbuf_set(uc_vm_t *vm, size_t nargs) 4005 { 4006 formatbuffer_t *buffer = formatbuffer_ctx(vm); 4007 uc_value_t *byte = uc_fn_arg(0); 4008 uc_value_t *from = uc_fn_arg(1); 4009 uc_value_t *to = uc_fn_arg(2); 4010 long long spos, epos; 4011 long bval; 4012 4013 if (!buffer) 4014 return NULL; 4015 4016 bval = 0; 4017 spos = 0; 4018 epos = buffer->length; 4019 4020 if (ucv_type(byte) == UC_STRING) 4021 bval = *ucv_string_get(byte); 4022 else if (byte && !ucv_as_long(vm, byte, &bval)) 4023 return NULL; 4024 4025 if (from && !ucv_as_longlong(vm, from, &spos)) 4026 return NULL; 4027 4028 if (to && !ucv_as_longlong(vm, to, &epos)) 4029 return NULL; 4030 4031 if (spos < 0) spos += buffer->length; 4032 if (spos < 0) spos = 0; 4033 4034 if (epos < 0) epos += buffer->length; 4035 4036 if (epos > spos) { 4037 if ((unsigned long long)epos > buffer->length) { 4038 if (!grow_buffer(vm, &buffer->resource.data, &buffer->capacity, epos)) 4039 return NULL; 4040 4041 buffer->length = epos; 4042 } 4043 4044 memset((char *)buffer->resource.data + sizeof(uc_string_t) + spos, 4045 bval, epos - spos); 4046 } 4047 4048 return ucv_get(&buffer->resource.header); 4049 } 4050 4051 /** 4052 * Extract and remove all content from the buffer. 4053 * 4054 * The `pull()` function returns all content of the buffer as a string 4055 * and resets the buffer to an empty state. 4056 * 4057 * @function module:struct.buffer#pull 4058 * 4059 * @returns {string} 4060 * A string containing all the buffer content. 4061 * 4062 * @example 4063 * const allData = buf.pull(); 4064 */ 4065 static uc_value_t * 4066 uc_fmtbuf_pull(uc_vm_t *vm, size_t nargs) 4067 { 4068 formatbuffer_t *buffer = formatbuffer_ctx(vm); 4069 uc_string_t *us; 4070 4071 if (!buffer) 4072 return NULL; 4073 4074 if (!buffer->resource.data) 4075 return ucv_string_new_length("", 0); 4076 4077 us = buffer->resource.data; 4078 us->header.type = UC_STRING; 4079 us->header.refcount = 1; 4080 us->length = buffer->length; 4081 4082 buffer->resource.data = NULL; 4083 buffer->capacity = 0; 4084 buffer->position = 0; 4085 buffer->length = 0; 4086 4087 return &us->header; 4088 } 4089 4090 4091 static const uc_function_list_t struct_inst_fns[] = { 4092 { "pack", uc_struct_pack }, 4093 { "unpack", uc_struct_unpack } 4094 }; 4095 4096 static const uc_function_list_t buffer_inst_fns[] = { 4097 { "pos", uc_fmtbuf_pos }, 4098 { "length", uc_fmtbuf_length }, 4099 { "start", uc_fmtbuf_start }, 4100 { "end", uc_fmtbuf_end }, 4101 { "set", uc_fmtbuf_set }, 4102 { "put", uc_fmtbuf_put }, 4103 { "get", uc_fmtbuf_get }, 4104 { "read", uc_fmtbuf_read }, 4105 { "slice", uc_fmtbuf_slice }, 4106 { "pull", uc_fmtbuf_pull }, 4107 }; 4108 4109 static const uc_function_list_t struct_fns[] = { 4110 { "pack", uc_pack }, 4111 { "unpack", uc_unpack }, 4112 { "new", uc_struct_new }, 4113 { "buffer", uc_fmtbuf_new } 4114 }; 4115 4116 void uc_module_init(uc_vm_t *vm, uc_value_t *scope) 4117 { 4118 optimize_functions(); 4119 4120 uc_function_list_register(scope, struct_fns); 4121 4122 uc_type_declare(vm, "struct.format", struct_inst_fns, free); 4123 uc_type_declare(vm, "struct.buffer", buffer_inst_fns, free); 4124 } 4125
This page was automatically generated by LXR 0.3.1. • OpenWrt