Print this page
OS-1723 DTrace should speak JSON (review fixes)

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/dtrace/dtrace.c
          +++ new/usr/src/uts/common/dtrace/dtrace.c
↓ open down ↓ 871 lines elided ↑ open up ↑
 872  872                  sz = dtrace_strlen(src, strsize) + 1;
 873  873          } else {
 874  874                  sz = type->dtdt_size;
 875  875          }
 876  876  
 877  877          return (dtrace_canload((uintptr_t)src, sz, mstate, vstate));
 878  878  }
 879  879  
 880  880  /*
 881  881   * Convert a string to a signed integer using safe loads.
      882 + *
      883 + * NOTE: This function uses various macros from strtolctype.h to manipulate
      884 + * digit values, etc -- these have all been checked to ensure they make
      885 + * no additional function calls.
 882  886   */
 883  887  static int64_t
 884  888  dtrace_strtoll(char *input, int base, size_t limit)
 885  889  {
 886  890          uintptr_t pos = (uintptr_t)input;
 887  891          int64_t val = 0;
 888  892          int x;
 889  893          boolean_t neg = B_FALSE;
 890  894          char c, cc, ccc;
 891  895          uintptr_t end = pos + limit;
 892  896  
 893      -        /* eat whitespace */
      897 +        /*
      898 +         * Consume any whitespace preceding digits.
      899 +         */
 894  900          while ((c = dtrace_load8(pos)) == ' ' || c == '\t')
 895  901                  pos++;
 896  902  
 897      -        /* sign? */
      903 +        /*
      904 +         * Handle an explicit sign if one is present.
      905 +         */
 898  906          if (c == '-' || c == '+') {
 899  907                  if (c == '-')
 900  908                          neg = B_TRUE;
 901  909                  c = dtrace_load8(++pos);
 902  910          }
 903  911  
 904      -        /* hex prefix? */
      912 +        /*
      913 +         * Check for an explicit hexadecimal prefix ("0x" or "0X") and skip it
      914 +         * if present.
      915 +         */
 905  916          if (base == 16 && c == '0' && ((cc = dtrace_load8(pos + 1)) == 'x' ||
 906  917              cc == 'X') && isxdigit(ccc = dtrace_load8(pos + 2))) {
 907      -                pos += 2; /* skip over leading "0x" or "0X" */
      918 +                pos += 2;
 908  919                  c = ccc;
 909  920          }
 910  921  
 911      -        /* read in digits */
      922 +        /*
      923 +         * Read in contiguous digits until the first non-digit character.
      924 +         */
 912  925          for (; pos < end && c != '\0' && lisalnum(c) && (x = DIGIT(c)) < base;
 913  926              c = dtrace_load8(++pos))
 914  927                  val = val * base + x;
 915  928  
 916  929          return (neg ? -val : val);
 917  930  }
 918  931  
 919  932  /*
 920  933   * Compare two strings using safe loads.
 921  934   */
↓ open down ↓ 2465 lines elided ↑ open up ↑
3387 3400  
3388 3401                  return ((uint64_t)lwp->lwp_errno);
3389 3402          }
3390 3403          default:
3391 3404                  DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
3392 3405                  return (0);
3393 3406          }
3394 3407  }
3395 3408  
3396 3409  
3397      -typedef enum json_state {
3398      -        JSON_REST = 1,
3399      -        JSON_OBJECT,
3400      -        JSON_STRING,
3401      -        JSON_STRING_ESCAPE,
3402      -        JSON_STRING_ESCAPE_UNICODE,
3403      -        JSON_COLON,
3404      -        JSON_COMMA,
3405      -        JSON_VALUE,
3406      -        JSON_IDENTIFIER,
3407      -        JSON_NUMBER,
3408      -        JSON_NUMBER_FRAC,
3409      -        JSON_NUMBER_EXP,
3410      -        JSON_COLLECT_OBJECT
3411      -} json_state_t;
     3410 +typedef enum dtrace_json_state {
     3411 +        DTRACE_JSON_REST = 1,
     3412 +        DTRACE_JSON_OBJECT,
     3413 +        DTRACE_JSON_STRING,
     3414 +        DTRACE_JSON_STRING_ESCAPE,
     3415 +        DTRACE_JSON_STRING_ESCAPE_UNICODE,
     3416 +        DTRACE_JSON_COLON,
     3417 +        DTRACE_JSON_COMMA,
     3418 +        DTRACE_JSON_VALUE,
     3419 +        DTRACE_JSON_IDENTIFIER,
     3420 +        DTRACE_JSON_NUMBER,
     3421 +        DTRACE_JSON_NUMBER_FRAC,
     3422 +        DTRACE_JSON_NUMBER_EXP,
     3423 +        DTRACE_JSON_COLLECT_OBJECT
     3424 +} dtrace_json_state_t;
3412 3425  
3413 3426  /*
3414 3427   * This function possesses just enough knowledge about JSON to extract a single
3415 3428   * value from a JSON string and store it in the scratch buffer.  It is able
3416 3429   * to extract nested object values, and members of arrays by index.
3417 3430   *
3418 3431   * elemlist is a list of JSON keys, stored as packed NUL-terminated strings, to
3419 3432   * be looked up as we descend into the object tree.  e.g.
3420 3433   *
3421 3434   *    foo[0].bar.baz[32] --> "foo" NUL "0" NUL "bar" NUL "baz" NUL "32" NUL
3422 3435   *       with nelems = 5.
     3436 + *
     3437 + * The run time of this function must be bounded above by strsize to limit the
     3438 + * amount of work done in probe context.  As such, it is implemented as a
     3439 + * simple state machine, reading one character at a time using safe loads
     3440 + * until we find the requested element, hit a parsing error or run off the
     3441 + * end of the object or string.
     3442 + *
     3443 + * As there is no way for a subroutine to return an error without interrupting
     3444 + * clause execution, we simply return NULL in the event of a missing key or any
     3445 + * other error condition.  Each NULL return in this function is commented with
     3446 + * the error condition it represents -- parsing or otherwise.
     3447 + *
     3448 + * The set of states for the state machine closely matches the JSON
     3449 + * specification (http://json.org/).  Briefly:
     3450 + *
     3451 + *   DTRACE_JSON_REST:
     3452 + *     Skip whitespace until we find either a top-level Object, moving
     3453 + *     to DTRACE_JSON_OBJECT; or an Array, moving to DTRACE_JSON_VALUE.
     3454 + *
     3455 + *   DTRACE_JSON_OBJECT:
     3456 + *     Locate the next key String in an Object.  Sets a flag to denote
     3457 + *     the next String as a key string and moves to DTRACE_JSON_STRING.
     3458 + *
     3459 + *   DTRACE_JSON_COLON:
     3460 + *     Skip whitespace until we find the colon that separates key Strings
     3461 + *     from their values.  Once found, move to DTRACE_JSON_VALUE.
     3462 + *
     3463 + *   DTRACE_JSON_VALUE:
     3464 + *     Detects the type of the next value (String, Number, Identifier, Object
     3465 + *     or Array) and routes to the states that process that type.  Here we also
     3466 + *     deal with the element selector list if we are requested to traverse down
     3467 + *     into the object tree.
     3468 + *
     3469 + *   DTRACE_JSON_COMMA:
     3470 + *     Skip whitespace until we find the comma that separates key-value pairs
     3471 + *     in Objects (returning to DTRACE_JSON_OBJECT) or values in Arrays
     3472 + *     (similarly DTRACE_JSON_VALUE).  All following literal value processing
     3473 + *     states return to this state at the end of their value, unless otherwise
     3474 + *     noted.
     3475 + *
     3476 + *   DTRACE_JSON_NUMBER, DTRACE_JSON_NUMBER_FRAC, DTRACE_JSON_NUMBER_EXP:
     3477 + *     Processes a Number literal from the JSON, including any exponent
     3478 + *     component that may be present.  Numbers are returned as strings, which
     3479 + *     may be passed to strtoll() if an integer is required.
     3480 + *
     3481 + *   DTRACE_JSON_IDENTIFIER:
     3482 + *     Processes a "true", "false" or "null" literal in the JSON.
     3483 + *
     3484 + *   DTRACE_JSON_STRING, DTRACE_JSON_STRING_ESCAPE,
     3485 + *   DTRACE_JSON_STRING_ESCAPE_UNICODE:
     3486 + *     Processes a String literal from the JSON, whether the String denotes
     3487 + *     a key, a value or part of a larger Object.  Handles all escape sequences
     3488 + *     present in the specification, including four-digit unicode characters,
     3489 + *     but merely includes the escape sequence without converting it to the
     3490 + *     actual escaped character.  If the String is flagged as a key, we
     3491 + *     move to DTRACE_JSON_COLON rather than DTRACE_JSON_COMMA.
     3492 + *
     3493 + *   DTRACE_JSON_COLLECT_OBJECT:
     3494 + *     This state collects an entire Object (or Array), correctly handling
     3495 + *     embedded strings.  If the full element selector list matches this nested
     3496 + *     object, we return the Object in full as a string.  If not, we use this
     3497 + *     state to skip to the next value at this level and continue processing.
     3498 + *
     3499 + * NOTE: This function uses various macros from strtolctype.h to manipulate
     3500 + * digit values, etc -- these have all been checked to ensure they make
     3501 + * no additional function calls.
3423 3502   */
3424 3503  static char *
3425 3504  dtrace_json(uint64_t size, uintptr_t json, char *elemlist, int nelems,
3426 3505      char *dest)
3427 3506  {
3428      -        json_state_t state = JSON_REST;
     3507 +        dtrace_json_state_t state = DTRACE_JSON_REST;
3429 3508          uint64_t i;
3430 3509          int64_t array_elem = INT64_MIN;
3431 3510          int64_t array_pos = 0;
3432 3511          uint8_t escape_unicount = 0;
3433 3512          boolean_t string_is_key = B_FALSE;
3434 3513          boolean_t collect_object = B_FALSE;
3435 3514          boolean_t found_key = B_FALSE;
3436 3515          boolean_t in_array = B_FALSE;
3437      -        uint8_t braces = 0, brackets = 0;
     3516 +        uint32_t braces = 0, brackets = 0;
3438 3517          char *elem = elemlist;
3439 3518          char *dd = dest;
3440 3519          uintptr_t cur;
3441 3520  
3442 3521          for (cur = json; cur < json + size; cur++) {
3443 3522                  char cc = dtrace_load8(cur);
3444      -                if (cc == '\0' || braces > 250)
     3523 +                if (cc == '\0')
3445 3524                          return (NULL);
3446 3525  
3447 3526                  switch (state) {
3448      -                case JSON_REST:
3449      -                        if (cc == ' ' || cc == '\t' || cc == '\n' || cc == '\r')
3450      -                                break; /* eat whitespace */
     3527 +                case DTRACE_JSON_REST:
     3528 +                        if (isspace(cc))
     3529 +                                break;
3451 3530  
3452 3531                          if (cc == '{') {
3453      -                                state = JSON_OBJECT;
     3532 +                                state = DTRACE_JSON_OBJECT;
3454 3533                                  break;
3455 3534                          }
3456 3535  
3457 3536                          if (cc == '[') {
3458 3537                                  in_array = B_TRUE;
3459 3538                                  array_pos = 0;
3460 3539                                  array_elem = dtrace_strtoll(elem, 10, size);
3461      -                                found_key = !!(array_elem == 0);
3462      -                                state = JSON_VALUE;
     3540 +                                found_key = array_elem == 0 ? B_TRUE : B_FALSE;
     3541 +                                state = DTRACE_JSON_VALUE;
3463 3542                                  break;
3464 3543                          }
3465 3544  
3466      -                        /* ERROR: expected object or array */
     3545 +                        /*
     3546 +                         * ERROR: expected to find a top-level object or array.
     3547 +                         */
3467 3548                          return (NULL);
3468      -                case JSON_OBJECT:
3469      -                        if (cc == ' ' || cc == '\t' || cc == '\n' || cc == '\r')
3470      -                                break; /* eat whitespace */
     3549 +                case DTRACE_JSON_OBJECT:
     3550 +                        if (isspace(cc))
     3551 +                                break;
3471 3552  
3472 3553                          if (cc == '"') {
3473      -                                state = JSON_STRING;
     3554 +                                state = DTRACE_JSON_STRING;
3474 3555                                  string_is_key = B_TRUE;
3475 3556                                  break;
3476 3557                          }
3477 3558  
3478      -                        /* ERROR: key not found! */
     3559 +                        /*
     3560 +                         * ERROR: either the object did not start with a key
     3561 +                         * string, or we've run off the end of the object
     3562 +                         * without finding the requested key.
     3563 +                         */
3479 3564                          return (NULL);
3480      -                case JSON_STRING:
     3565 +                case DTRACE_JSON_STRING:
3481 3566                          if (cc == '\\') {
3482 3567                                  *dd++ = '\\';
3483      -                                state = JSON_STRING_ESCAPE;
     3568 +                                state = DTRACE_JSON_STRING_ESCAPE;
3484 3569                                  break;
3485 3570                          }
3486 3571  
3487 3572                          if (cc == '"') {
3488 3573                                  if (collect_object) {
3489 3574                                          /*
3490 3575                                           * We don't reset the dest here, as
3491 3576                                           * the string is part of a larger
3492 3577                                           * object being collected.
3493 3578                                           */
3494 3579                                          *dd++ = cc;
3495 3580                                          collect_object = B_FALSE;
3496      -                                        state = JSON_COLLECT_OBJECT;
     3581 +                                        state = DTRACE_JSON_COLLECT_OBJECT;
3497 3582                                          break;
3498 3583                                  }
3499 3584                                  *dd = '\0';
3500 3585                                  dd = dest; /* reset string buffer */
3501 3586                                  if (string_is_key) {
3502 3587                                          if (dtrace_strncmp(dest, elem,
3503 3588                                              size) == 0)
3504 3589                                                  found_key = B_TRUE;
3505 3590                                  } else if (found_key) {
3506 3591                                          if (nelems > 1) {
3507 3592                                                  /*
3508 3593                                                   * We expected an object, not
3509 3594                                                   * this string.
3510 3595                                                   */
3511 3596                                                  return (NULL);
3512 3597                                          }
3513 3598                                          return (dest);
3514 3599                                  }
3515      -                                state = string_is_key ? JSON_COLON :
3516      -                                    JSON_COMMA;
     3600 +                                state = string_is_key ? DTRACE_JSON_COLON :
     3601 +                                    DTRACE_JSON_COMMA;
3517 3602                                  string_is_key = B_FALSE;
3518 3603                                  break;
3519 3604                          }
3520 3605  
3521 3606                          *dd++ = cc;
3522 3607                          break;
3523      -                case JSON_STRING_ESCAPE:
     3608 +                case DTRACE_JSON_STRING_ESCAPE:
3524 3609                          *dd++ = cc;
3525 3610                          if (cc == 'u') {
3526 3611                                  escape_unicount = 0;
3527      -                                state = JSON_STRING_ESCAPE_UNICODE;
     3612 +                                state = DTRACE_JSON_STRING_ESCAPE_UNICODE;
3528 3613                          } else {
3529      -                                state = JSON_STRING;
     3614 +                                state = DTRACE_JSON_STRING;
3530 3615                          }
3531 3616                          break;
3532      -                case JSON_STRING_ESCAPE_UNICODE:
3533      -                        if (!isxdigit(cc))
3534      -                                /* ERROR: unvalid unicode escape */
     3617 +                case DTRACE_JSON_STRING_ESCAPE_UNICODE:
     3618 +                        if (!isxdigit(cc)) {
     3619 +                                /*
     3620 +                                 * ERROR: invalid unicode escape, expected
     3621 +                                 * four valid hexidecimal digits.
     3622 +                                 */ 
3535 3623                                  return (NULL);
     3624 +                        }
3536 3625  
3537 3626                          *dd++ = cc;
3538 3627                          if (++escape_unicount == 4)
3539      -                                state = JSON_STRING;
     3628 +                                state = DTRACE_JSON_STRING;
3540 3629                          break;
3541      -                case JSON_COLON:
3542      -                        if (cc == ' ' || cc == '\t' || cc == '\n' || cc == '\r')
3543      -                                break; /* eat whitespace */
     3630 +                case DTRACE_JSON_COLON:
     3631 +                        if (isspace(cc))
     3632 +                                break;
3544 3633  
3545 3634                          if (cc == ':') {
3546      -                                state = JSON_VALUE;
     3635 +                                state = DTRACE_JSON_VALUE;
3547 3636                                  break;
3548 3637                          }
3549 3638  
3550      -                        /* ERROR: expected colon */
     3639 +                        /*
     3640 +                         * ERROR: expected a colon.
     3641 +                         */
3551 3642                          return (NULL);
3552      -                case JSON_COMMA:
3553      -                        if (cc == ' ' || cc == '\t' || cc == '\n' || cc == '\r')
3554      -                                break; /* eat whitespace */
     3643 +                case DTRACE_JSON_COMMA:
     3644 +                        if (isspace(cc))
     3645 +                                break;
3555 3646  
3556 3647                          if (cc == ',') {
3557 3648                                  if (in_array) {
3558      -                                        state = JSON_VALUE;
     3649 +                                        state = DTRACE_JSON_VALUE;
3559 3650                                          if (++array_pos == array_elem)
3560 3651                                                  found_key = B_TRUE;
3561 3652                                  } else {
3562      -                                        state = JSON_OBJECT;
     3653 +                                        state = DTRACE_JSON_OBJECT;
3563 3654                                  }
3564 3655                                  break;
3565 3656                          }
3566 3657  
3567      -                        /* ERROR: key not found or expected comma */
     3658 +                        /*
     3659 +                         * ERROR: either we hit an unexpected character, or
     3660 +                         * we reached the end of the object or array without
     3661 +                         * finding the requested key.
     3662 +                         */
3568 3663                          return (NULL);
3569      -                case JSON_IDENTIFIER:
3570      -                        if (cc >= 'a' && cc <= 'z') {
     3664 +                case DTRACE_JSON_IDENTIFIER:
     3665 +                        if (islower(cc)) {
3571 3666                                  *dd++ = cc;
3572 3667                                  break;
3573 3668                          }
3574 3669  
3575 3670                          *dd = '\0';
3576 3671                          dd = dest; /* reset string buffer */
3577 3672  
3578 3673                          if (dtrace_strncmp(dest, "true", 5) == 0 ||
3579 3674                              dtrace_strncmp(dest, "false", 6) == 0 ||
3580 3675                              dtrace_strncmp(dest, "null", 5) == 0) {
3581 3676                                  if (found_key) {
3582 3677                                          if (nelems > 1) {
3583 3678                                                  /*
3584      -                                                 * We expected an object, not
3585      -                                                 * this identifier.
     3679 +                                                 * ERROR: We expected an object,
     3680 +                                                 * not this identifier.
3586 3681                                                   */
3587 3682                                                  return (NULL);
3588 3683                                          }
3589 3684                                          return (dest);
3590 3685                                  } else {
3591 3686                                          cur--;
3592      -                                        state = JSON_COMMA;
     3687 +                                        state = DTRACE_JSON_COMMA;
3593 3688                                          break;
3594 3689                                  }
3595 3690                          }
3596 3691  
3597      -                        /* ERROR: unexpected identifier */
     3692 +                        /*
     3693 +                         * ERROR: we did not recognise the identifier as one
     3694 +                         * of those in the JSON specification.
     3695 +                         */
3598 3696                          return (NULL);
3599      -                case JSON_NUMBER:
     3697 +                case DTRACE_JSON_NUMBER:
3600 3698                          if (cc == '.') {
3601 3699                                  *dd++ = cc;
3602      -                                state = JSON_NUMBER_FRAC;
     3700 +                                state = DTRACE_JSON_NUMBER_FRAC;
3603 3701                                  break;
3604 3702                          }
3605 3703  
3606      -                        if (cc == 'x' || cc == 'X')
3607      -                                /* ERROR: spec explicitly excludes hex */
     3704 +                        if (cc == 'x' || cc == 'X') {
     3705 +                                /*
     3706 +                                 * ERROR: specification explicitly excludes
     3707 +                                 * hexidecimal or octal numbers.
     3708 +                                 */
3608 3709                                  return (NULL);
     3710 +                        }
3609 3711  
3610 3712                          /* FALLTHRU */
3611      -                case JSON_NUMBER_FRAC:
     3713 +                case DTRACE_JSON_NUMBER_FRAC:
3612 3714                          if (cc == 'e' || cc == 'E') {
3613 3715                                  *dd++ = cc;
3614      -                                state = JSON_NUMBER_EXP;
     3716 +                                state = DTRACE_JSON_NUMBER_EXP;
3615 3717                                  break;
3616 3718                          }
3617 3719  
3618 3720                          if (cc == '+' || cc == '-') {
3619 3721                                  /*
3620      -                                 * ERROR: expect sign as part of exponent only
     3722 +                                 * ERROR: expect sign as part of exponent only.
3621 3723                                   */
3622 3724                                  return (NULL);
3623 3725                          }
3624 3726                          /* FALLTHRU */
3625      -                case JSON_NUMBER_EXP:
3626      -                        if ((cc >= '0' && cc <= '9') || cc == '+' ||
3627      -                            cc == '-') {
     3727 +                case DTRACE_JSON_NUMBER_EXP:
     3728 +                        if (isdigit(cc) || cc == '+' || cc == '-') {
3628 3729                                  *dd++ = cc;
3629 3730                                  break;
3630 3731                          }
3631 3732  
3632 3733                          *dd = '\0';
3633 3734                          dd = dest; /* reset string buffer */
3634 3735                          if (found_key) {
3635 3736                                  if (nelems > 1) {
3636 3737                                          /*
3637      -                                         * We expected an object, not this
3638      -                                         * number.
     3738 +                                         * ERROR: We expected an object, not
     3739 +                                         * this number.
3639 3740                                           */
3640 3741                                          return (NULL);
3641 3742                                  }
3642 3743                                  return (dest);
3643 3744                          }
3644 3745  
3645 3746                          cur--;
3646      -                        state = JSON_COMMA;
     3747 +                        state = DTRACE_JSON_COMMA;
3647 3748                          break;
3648      -                case JSON_VALUE:
3649      -                        if (cc == ' ' || cc == '\t' || cc == '\n' || cc == '\r')
3650      -                                break; /* eat whitespace */
     3749 +                case DTRACE_JSON_VALUE:
     3750 +                        if (isspace(cc))
     3751 +                                break;
3651 3752  
3652 3753                          if (cc == '{' || cc == '[') {
3653 3754                                  if (nelems > 1 && found_key) {
3654      -                                        in_array = !!(cc == '[');
     3755 +                                        in_array = cc == '[' ? B_TRUE : B_FALSE;
3655 3756                                          /*
3656 3757                                           * If our element selector directs us
3657 3758                                           * to descend into this nested object,
3658 3759                                           * then move to the next selector
3659 3760                                           * element in the list and restart the
3660 3761                                           * state machine.
3661 3762                                           */
3662 3763                                          while (*elem != '\0')
3663 3764                                                  elem++;
3664 3765                                          elem++; /* skip the inter-element NUL */
3665 3766                                          nelems--;
3666 3767                                          dd = dest;
3667 3768                                          if (in_array) {
3668      -                                                state = JSON_VALUE;
     3769 +                                                state = DTRACE_JSON_VALUE;
3669 3770                                                  array_pos = 0;
3670 3771                                                  array_elem = dtrace_strtoll(
3671 3772                                                      elem, 10, size);
3672      -                                                found_key = !!(array_elem == 0);
     3773 +                                                found_key = array_elem == 0 ?
     3774 +                                                    B_TRUE : B_FALSE;
3673 3775                                          } else {
3674 3776                                                  found_key = B_FALSE;
3675      -                                                state = JSON_OBJECT;
     3777 +                                                state = DTRACE_JSON_OBJECT;
3676 3778                                          }
3677 3779                                          break;
3678 3780                                  }
3679 3781  
3680 3782                                  /*
3681 3783                                   * Otherwise, we wish to either skip this
3682 3784                                   * nested object or return it in full.
3683 3785                                   */
3684 3786                                  if (cc == '[')
3685 3787                                          brackets = 1;
3686 3788                                  else
3687 3789                                          braces = 1;
3688 3790                                  *dd++ = cc;
3689      -                                state = JSON_COLLECT_OBJECT;
     3791 +                                state = DTRACE_JSON_COLLECT_OBJECT;
3690 3792                                  break;
3691 3793                          }
3692 3794  
3693 3795                          if (cc == '"') {
3694      -                                state = JSON_STRING;
     3796 +                                state = DTRACE_JSON_STRING;
3695 3797                                  break;
3696 3798                          }
3697 3799  
3698      -                        if (cc >= 'a' && cc <= 'z') {
3699      -                                /* Here we deal with true, false and null */
     3800 +                        if (islower(cc)) {
     3801 +                                /*
     3802 +                                 * Here we deal with true, false and null.
     3803 +                                 */
3700 3804                                  *dd++ = cc;
3701      -                                state = JSON_IDENTIFIER;
     3805 +                                state = DTRACE_JSON_IDENTIFIER;
3702 3806                                  break;
3703 3807                          }
3704 3808  
3705      -                        if (cc == '-' || (cc >= '0' && cc <= '9')) {
     3809 +                        if (cc == '-' || isdigit(cc)) {
3706 3810                                  *dd++ = cc;
3707      -                                state = JSON_NUMBER;
     3811 +                                state = DTRACE_JSON_NUMBER;
3708 3812                                  break;
3709 3813                          }
3710 3814  
3711      -                        /* ERROR: unexpected character */
     3815 +                        /*
     3816 +                         * ERROR: unexpected character at start of value.
     3817 +                         */
3712 3818                          return (NULL);
3713      -                case JSON_COLLECT_OBJECT:
     3819 +                case DTRACE_JSON_COLLECT_OBJECT:
3714 3820                          if (cc == '\0')
3715      -                                /* ERROR: unexpected end of input */
     3821 +                                /*
     3822 +                                 * ERROR: unexpected end of input.
     3823 +                                 */
3716 3824                                  return (NULL);
3717 3825  
3718 3826                          *dd++ = cc;
3719 3827                          if (cc == '"') {
3720 3828                                  collect_object = B_TRUE;
3721      -                                state = JSON_STRING;
     3829 +                                state = DTRACE_JSON_STRING;
3722 3830                                  break;
3723 3831                          }
3724 3832  
3725 3833                          if (cc == ']') {
3726 3834                                  if (brackets-- == 0) {
3727      -                                        /* ERROR: unbalanced brackets */
     3835 +                                        /*
     3836 +                                         * ERROR: unbalanced brackets.
     3837 +                                         */
3728 3838                                          return (NULL);
3729 3839                                  }
3730 3840                          } else if (cc == '}') {
3731 3841                                  if (braces-- == 0) {
3732      -                                        /* ERROR: unbalanced braces */
     3842 +                                        /*
     3843 +                                         * ERROR: unbalanced braces.
     3844 +                                         */
3733 3845                                          return (NULL);
3734 3846                                  }
3735 3847                          } else if (cc == '{') {
3736 3848                                  braces++;
3737 3849                          } else if (cc == '[') {
3738 3850                                  brackets++;
3739 3851                          }
3740 3852  
3741 3853                          if (brackets == 0 && braces == 0) {
3742 3854                                  if (found_key) {
3743 3855                                          *dd = '\0';
3744 3856                                          return (dest);
3745 3857                                  }
3746 3858                                  dd = dest; /* reset string buffer */
3747      -                                state = JSON_COMMA;
     3859 +                                state = DTRACE_JSON_COMMA;
3748 3860                          }
3749 3861                          break;
3750 3862                  }
3751 3863          }
3752 3864          return (NULL);
3753 3865  }
3754 3866  
3755 3867  /*
3756 3868   * Emulate the execution of DTrace ID subroutines invoked by the call opcode.
3757 3869   * Notice that we don't bother validating the proper number of arguments or
↓ open down ↓ 719 lines elided ↑ open up ↑
4477 4589                          break;
4478 4590                  }
4479 4591  
4480 4592                  /*
4481 4593                   * Read the element selector and split it up into a packed list
4482 4594                   * of strings.
4483 4595                   */
4484 4596                  for (cur = elem; cur < elem + elemlen; cur++) {
4485 4597                          char cc = dtrace_load8(cur);
4486 4598  
4487      -                        if (cur == elem && cc == '[')
4488      -                                /* first element selector may be an array */
     4599 +                        if (cur == elem && cc == '[') {
     4600 +                                /*
     4601 +                                 * If the first element selector key is
     4602 +                                 * actually an array index then ignore the
     4603 +                                 * bracket.
     4604 +                                 */
4489 4605                                  continue;
     4606 +                        }
4490 4607  
4491 4608                          if (cc == ']')
4492 4609                                  continue;
4493 4610  
4494 4611                          if (cc == '.' || cc == '[') {
4495 4612                                  nelems++;
4496 4613                                  cc = '\0';
4497 4614                          }
4498 4615  
4499 4616                          *ee++ = cc;
↓ open down ↓ 12273 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX