Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-40706

JSON_LENGTH answers 1 for documents it never finished reading, including bare scalars with trailing rubbish

    XMLWordPrintable

Details

    • Bug
    • Status: Open (View Workflow)
    • Major
    • Resolution: Unresolved
    • 10.11, 11.4, 11.8, 12.3, 13.0
    • None
    • JSON

    Description

      JSON_LENGTH is documented to raise an error when the document is
      invalid. A scalar value is answered for and returned before the check
      that the rest of the document parses, so several byte strings that are
      not documents come back with a length of 1 and no diagnostic.

      SELECT JSON_LENGTH('01') AS v;
      v
      1

      01 is not a JSON number: a leading zero may not be followed by another
      digit. The server agrees everywhere else:

      SELECT JSON_VALID('01') AS va, JSON_TYPE('01') AS ty, JSON_DEPTH('01') AS de;
      va    ty    de
      0     NULL  NULL
      Warnings:
      Note     4038  Syntax error in JSON text in argument 1
                    to function 'json_valid' at position 2
      Warning  4038  Syntax error in JSON text in argument 1
                    to function 'json_type' at position 2
      Warning  4038  Syntax error in JSON text in argument 1
                    to function 'json_depth' at position 2

      How to repeat

      SELECT JSON_LENGTH('01')                    AS bad_number;   -- 1, silent
      SELECT JSON_LENGTH('{"a":1 "b":2}', '$.a')  AS with_path;    -- 1, silent
      SELECT JSON_LENGTH('[1 2]', '$[0]')         AS with_index;   -- 1, silent

      The same function refuses the same bytes when the path is left off:

      -- NULL + Warning 4038 at position 8
      SELECT JSON_LENGTH('{"a":1 "b":2}') AS v;
      -- NULL + Warning 4038 at position 4
      SELECT JSON_LENGTH('[1 2]')         AS v;

      and it refuses trailing rubbish after a container while accepting it
      after a scalar:

      SELECT JSON_LENGTH('{"a":1} rubbish') AS after_a_container;
      -- NULL + Warning 4038 at position 9
      SELECT JSON_LENGTH('1 rubbish')       AS after_a_scalar;
      -- 1, silent

      Root cause

      `sql/item_jsonfunc.cc` returns for a scalar value before the loop that
      reads the rest of the document to check it:

        if (json_value_scalar(&je))
          return 1;

      The loop twenty lines below, introduced with the comment *"Parse to the
      end of the JSON just to check it's valid"*, is never reached on that
      path.

      Contract, `scripts/fill_help_tables.sql:445`: *"An error occurs if the
      JSON document is invalid, the path is invalid or if the path contains a
      or wildcard."*

      Affected versions

      JSON_LENGTH was added in 10.2.3 and the scalar early return has
      been there throughout.

      Verified on 10.11 only (10.11.19-MariaDB-debug, commit 1dab253482d).
      Other branches were not tested.

      Note

      Found while auditing the JSON functions against their documented
      contracts. The container cases are pinned
      (func_json.result:468, :2899); nothing pins the scalar path.

      Attachments

        Issue Links

          Activity

            People

              Unassigned Unassigned
              arcivanov Arcadiy Ivanov
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated:

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.