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