Changeset: daa576df6914 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=daa576df6914
Modified Files:
        sql/server/sql_atom.c
        sql/server/sql_semantic.c
        sql/test/merge-partitions/Tests/mergepart20.stable.out
Branch: Nov2019
Log Message:

Escape SQL strings and avoid possible buffer overflows if so


diffs (182 lines):

diff --git a/sql/server/sql_atom.c b/sql/server/sql_atom.c
--- a/sql/server/sql_atom.c
+++ b/sql/server/sql_atom.c
@@ -456,10 +456,17 @@ atom2sql(atom *a)
                        return _STRDUP("true");
                return _STRDUP("false");
        case EC_CHAR:
-       case EC_STRING:
+       case EC_STRING: {
+               char *val, *res;
                assert(a->data.vtype == TYPE_str && a->data.val.sval);
-               sprintf(buf, "'%s'", a->data.val.sval);
-               break;
+
+               if (!(val = sql_escape_str(a->data.val.sval)))
+                       return NULL;
+               if ((res = NEW_ARRAY(char, strlen(val) + 3)))
+                       stpcpy(stpcpy(stpcpy(res, "'"), val), "'");
+               c_delete(val);
+               return res;
+       } break;
        case EC_BLOB:
                /* TODO atom to string */
                break;
@@ -571,8 +578,21 @@ atom2sql(atom *a)
        case EC_DATE:
        case EC_TIMESTAMP:
                if (a->data.vtype == TYPE_str) {
-                       assert(a->data.val.sval);
-                       sprintf(buf, "%s '%s'", a->tpe.type->sqlname, 
a->data.val.sval);
+                       char *val1 = sql_escape_str(a->tpe.type->sqlname), 
*val2 = sql_escape_str(a->data.val.sval), *res;
+
+                       if (!val1 || !val2) {
+                               c_delete(val1);
+                               c_delete(val2);
+                               return NULL;
+                       }
+                               
+                       if ((res = NEW_ARRAY(char, strlen(val1) + strlen(val2) 
+ 4)))
+                               stpcpy(stpcpy(stpcpy(stpcpy(res, val1)," '"), 
val2), "'");
+                       c_delete(val1);
+                       c_delete(val2);
+                       return res;
+               } else {
+                       snprintf(buf, BUFSIZ, "atom2sql(TYPE_%d) not 
implemented", a->data.vtype);
                }
                break;
        default:
diff --git a/sql/server/sql_semantic.c b/sql/server/sql_semantic.c
--- a/sql/server/sql_semantic.c
+++ b/sql/server/sql_semantic.c
@@ -252,7 +252,8 @@ supertype(sql_subtype *super, sql_subtyp
        return super;
 }
 
-char * toUpperCopy(char *dest, const char *src) 
+char *
+toUpperCopy(char *dest, const char *src) 
 {
        size_t i, len;
 
@@ -269,7 +270,8 @@ char * toUpperCopy(char *dest, const cha
        return(dest);
 }
 
-char *dlist2string(mvc *sql, dlist *l, int expression, char **err)
+char *
+dlist2string(mvc *sql, dlist *l, int expression, char **err)
 {
        char *b = NULL;
        dnode *n;
@@ -302,7 +304,8 @@ char *dlist2string(mvc *sql, dlist *l, i
        return b;
 }
 
-char *symbol2string(mvc *sql, symbol *se, int expression, char **err) /**/
+char *
+symbol2string(mvc *sql, symbol *se, int expression, char **err) /**/
 {
        int len = 0;
        char buf[BUFSIZ];
@@ -372,18 +375,25 @@ char *symbol2string(mvc *sql, symbol *se
                        strcpy(buf,"NULL");
                break;
        }
-       case SQL_NEXT:{
-               const char *seq = qname_table(se->data.lval);
-               const char *sname = qname_schema(se->data.lval);
-               const char *s;
+       case SQL_NEXT: {
+               const char *seq = qname_table(se->data.lval), *sname = 
qname_schema(se->data.lval);
+               char *res;
 
                if (!sname)
                        sname = sql->session->schema->base.name;
-               s = sql_escape_ident(seq);
-               if(!s)
+
+               const char *sname_esc = sql_escape_ident(sname);
+               const char *seq_esc = sql_escape_ident(seq);
+               if (!seq_esc || !sname_esc) {
+                       c_delete(sname_esc);
+                       c_delete(seq_esc);
                        return NULL;
-               len = snprintf( buf+len, BUFSIZ-len, "next value for 
\"%s\".\"%s\"", sname, s);
-               c_delete(s);
+               }
+               if ((res = NEW_ARRAY(char, strlen("next value for \"") + 
strlen(sname_esc) + strlen(seq_esc) + 5)))
+                       stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(res, "next value for 
\""), sname_esc), "\".\""), seq_esc), "\"");
+               c_delete(sname_esc);
+               c_delete(seq_esc);
+               return res;
        }       break;
        case SQL_IDENT:
        case SQL_COLUMN: {
@@ -395,19 +405,33 @@ char *symbol2string(mvc *sql, symbol *se
                        return atom2sql(a);
                } else if (expression && dlist_length(l) == 1 && l->h->type == 
type_string) {
                        /* when compiling an expression, a column of a table 
might be present in the symbol, so we need this case */
-                       return _STRDUP(l->h->data.sval);
-               } else if (expression && dlist_length(l) == 2 && l->h->type == 
type_string && l->h->next->type == type_string) {
-                       char *first = l->h->data.sval;
-                       char *second = l->h->next->data.sval;
+                       const char *l_escp = sql_escape_ident(l->h->data.sval);
                        char *res;
 
-                       if(!first || !second) {
+                       if (!l_escp)
+                               return NULL;
+
+                       if ((res = NEW_ARRAY(char, strlen(l_escp) + 3)))
+                               stpcpy(stpcpy(stpcpy(res, "\""), l_escp), "\"");
+                       c_delete(l_escp);
+                       return res;
+               } else if (expression && dlist_length(l) == 2 && l->h->type == 
type_string && l->h->next->type == type_string) {
+                       char *first = l->h->data.sval, *second = 
l->h->next->data.sval, *res;
+
+                       if (!first || !second)
+                               return NULL;
+                       const char *first_esc = sql_escape_ident(first);
+                       const char *second_esc = sql_escape_ident(first);
+                       if (!first_esc || !second_esc) {
+                               c_delete(first_esc);
+                               c_delete(second_esc);
                                return NULL;
                        }
-                       res = NEW_ARRAY(char, strlen(first) + strlen(second) + 
2);
-                       if (res) {
-                               stpcpy(stpcpy(stpcpy(res, first), "."), second);
-                       }
+
+                       if ((res = NEW_ARRAY(char, strlen(first_esc) + 
strlen(second_esc) + 6)))
+                               stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(res, "\""), 
first_esc), "\".\""), second_esc), "\"");
+                       c_delete(first_esc);
+                       c_delete(second);
                        return res;
                } else {
                        char *e = dlist2string(sql, l, expression, err);
@@ -429,8 +453,7 @@ char *symbol2string(mvc *sql, symbol *se
                        _DELETE(val);
                        return NULL;
                }
-               len = snprintf( buf+len, BUFSIZ-len, "cast ( %s as %s )",
-                               val, tpe);
+               len = snprintf( buf+len, BUFSIZ-len, "cast ( %s as %s )", val, 
tpe);
                _DELETE(val);
                _DELETE(tpe);
                break;
diff --git a/sql/test/merge-partitions/Tests/mergepart20.stable.out 
b/sql/test/merge-partitions/Tests/mergepart20.stable.out
--- a/sql/test/merge-partitions/Tests/mergepart20.stable.out
+++ b/sql/test/merge-partitions/Tests/mergepart20.stable.out
@@ -71,8 +71,8 @@ stdout of test 'mergepart20` in director
 % sys.table_partitions,        sys.table_partitions # table_name
 % column_id,   expression # name
 % int, varchar # type
-% 1,   6 # length
-[ NULL,        "md5(a)"        ]
+% 1,   8 # length
+[ NULL,        "md5(\"a\")"    ]
 #ALTER TABLE testme ADD TABLE subtable1 AS PARTITION FROM 
'00000000000000000000000000000000' TO '7fffffffffffffffffffffffffffffff';
 #ALTER TABLE testme ADD TABLE subtable2 AS PARTITION FROM 
'80000000000000000000000000000000' TO 'ffffffffffffffffffffffffffffffff';
 #INSERT INTO testme VALUES (1, 'first'), (2000, 'second'), (3, 'third'), 
(4000, 'fourth');
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to