Uploaded image for project: 'MariaDB Connector/Python'
  1. MariaDB Connector/Python
  2. CONPY-334

Parsing of a statement with literals fails to identify parameters in some scenarios

    XMLWordPrintable

Details

    • Bug
    • Status: Closed (View Workflow)
    • Minor
    • Resolution: Fixed
    • 1.1.14
    • 1.1.15
    • Parser
    • None
    • 3.12.12

    Description

      Hi Developers,

      using version 1.1.14 of the connector some literals present into an SQL statement are not correctly parsed, causing a syntax error on application side because any qestion mark (qmark) present after the literal is ignored. For example, the following statement:

      SELECT value FROM mytable WHERE lower(convert(trim(BOTH '"' FROM convert(value, CHAR)) using utf8mb4)) LIKE lower(?)
      

      is not correctly understood, leaving the qmark not identified. Investigating further this issue, I observed that the logic used to early identify the start of the literals doesn't manage well the literal of above statement, because it has a single double quote between two single quotes. In other words, the literal itself is a single double quote. Other more complex testing statements can be provided.

      Given that this issue was blocking for my use case, I quickly fixed it using the following logic:

      diff --git a/include/mariadb_python.h b/include/mariadb_python.h
      index bb2a24d..be753a2 100755
      --- a/include/mariadb_python.h
      +++ b/include/mariadb_python.h
      @@ -224,7 +224,6 @@ typedef struct st_ext_field_type {
       typedef struct st_parser {
           MrdbString statement;
           MrdbString *keys;
      -    uint8_t in_literal[3];
           uint8_t in_comment;
           uint8_t in_values;
           uint8_t is_insert;
      diff --git a/mariadb/mariadb_parser.c b/mariadb/mariadb_parser.c
      index 25fa17b..a3d0caf 100755
      --- a/mariadb/mariadb_parser.c
      +++ b/mariadb/mariadb_parser.c
      @@ -18,11 +18,9 @@
        ****************************************************************************/
       
       #include <mariadb_python.h>
      +#include <stdbool.h>
       
       #define IS_WHITESPACE(a) (a==32 || a==9 || a==10 || a==13)
      -#define IN_LITERAL(p) ((p)->in_literal[0] ||\
      -                      (p)->in_literal[1] ||\
      -                      (p)->in_literal[2])
       
       const char *comment_start= "/*";
       const char *comment_end= "*/";
      @@ -130,6 +128,8 @@ MrdbParser_parse(MrdbParser *p, uint8_t is_batch,
           char *a, *end;
           char lastchar= 0;
           uint8_t i;
      +    bool literal_string = false;
      +    char literal_start_char = '\0';
       
           if (errmsg_len)
               *errmsg= 0;
      @@ -151,25 +151,33 @@ MrdbParser_parse(MrdbParser *p, uint8_t is_batch,
           while (a <= end)
           {
       cont:
      -/*        if (isutf8(*a)) {
      -          a++;
      -          continue;
      -        } */
               /* check literals */
      -        for (i=0; i < 3; i++)
      -        {
      -            if (*a == literals[i])
      -            {
      -                p->in_literal[i]= !(p->in_literal[i]);
      -                a++;
      -                goto cont;
      +        if (!literal_string) {
      +            for (i=0; i < 3; i++) {
      +                if (*a == literals[i]) {
      +                    literal_string = true;
      +                    literal_start_char = *a;
      +                    a++;
      +                    goto cont;
      +                }
                   }
               }
               /* nothing to do, if we are inside a comment or literal */
      -        if (IN_LITERAL(p))
      -        {
      -            a++;
      -            continue;
      +        if (literal_string) {
      +            if (*a == '\\' && a+1 < end) {
      +                for (i=0; i < 3; i++) {
      +                    if (*a == literals[i]) {
      +                        a++; // Skip backslash
      +                    }
      +                }
      +            }
      +
      +            if (*a == literal_start_char && (a == 0 || *(a-1) != '\\')) {
      +                // End of string found (not escaped)
      +                literal_string = false;
      +                literal_start_char = '\0';
      +                goto cont;
      +            }
               }
               /* check comment */
               if (!p->in_comment)
      

      Can you have a review of this issue and, if confirmed, evaluate if a similar fix can be added to MariaDB Python connector?

      Thanks
      Max

      Attachments

        Activity

          People

            georg Georg Richter
            mottimo Max
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Git Integration

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