Changeset: e1fa36d687f5 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=e1fa36d687f5
Modified Files:
sql/server/rel_partition.c
sql/server/rel_propagate.c
sql/server/sql_atom.c
sql/server/sql_partition.c
sql/server/sql_semantic.c
Branch: Apr2019
Log Message:
Check for stack overflows while compiling expressions, disallow SQL parameters
and variables as well.
diffs (259 lines):
diff --git a/sql/server/rel_partition.c b/sql/server/rel_partition.c
--- a/sql/server/rel_partition.c
+++ b/sql/server/rel_partition.c
@@ -41,8 +41,13 @@ rel_getcount(mvc *sql, sql_rel *rel)
}
static void
-find_basetables( sql_rel *rel, list *tables )
+find_basetables(mvc *sql, sql_rel *rel, list *tables )
{
+ if (THRhighwater()) {
+ (void) sql_error(sql, 10, SQLSTATE(42000) "query too complex:
running out of stack space");
+ return;
+ }
+
if (!rel)
return;
switch (rel->op) {
@@ -68,9 +73,9 @@ find_basetables( sql_rel *rel, list *tab
case op_inter:
case op_except:
if (rel->l)
- find_basetables(rel->l, tables);
+ find_basetables(sql, rel->l, tables);
if (rel->r)
- find_basetables(rel->r, tables);
+ find_basetables(sql, rel->r, tables);
break;
case op_groupby:
case op_project:
@@ -78,7 +83,7 @@ find_basetables( sql_rel *rel, list *tab
case op_topn:
case op_sample:
if (rel->l)
- find_basetables(rel->l, tables);
+ find_basetables(sql, rel->l, tables);
break;
case op_ddl:
break;
@@ -87,7 +92,7 @@ find_basetables( sql_rel *rel, list *tab
case op_delete:
case op_truncate:
if (rel->r)
- find_basetables(rel->r, tables);
+ find_basetables(sql, rel->r, tables);
break;
}
}
@@ -98,7 +103,7 @@ static sql_rel *
list *tables = sa_list(sql->sa);
/* find basetable relations */
/* mark one (largest) with REL_PARTITION */
- find_basetables(rel, tables);
+ find_basetables(sql, rel, tables);
if (list_length(tables)) {
sql_rel *r;
node *n;
@@ -137,6 +142,8 @@ has_groupby(sql_rel *rel)
sql_rel *
rel_partition(mvc *sql, sql_rel *rel)
{
+ if (THRhighwater())
+ return sql_error(sql, 10, SQLSTATE(42000) "query too complex:
running out of stack space");
(void)sql;
if (rel->op == op_basetable) {
rel->flag = REL_PARTITION;
diff --git a/sql/server/rel_propagate.c b/sql/server/rel_propagate.c
--- a/sql/server/rel_propagate.c
+++ b/sql/server/rel_propagate.c
@@ -412,6 +412,9 @@ static sql_rel* rel_change_base_table(mv
static sql_exp*
exp_change_column_table(mvc *sql, sql_exp *e, sql_table* oldt, sql_table* newt)
{
+ if (THRhighwater())
+ return sql_error(sql, 10, SQLSTATE(42000) "query too complex:
running out of stack space");
+
if (!e)
return NULL;
switch(e->type) {
@@ -485,6 +488,9 @@ exp_change_column_table(mvc *sql, sql_ex
static sql_rel*
rel_change_base_table(mvc* sql, sql_rel* rel, sql_table* oldt, sql_table* newt)
{
+ if (THRhighwater())
+ return sql_error(sql, 10, SQLSTATE(42000) "query too complex:
running out of stack space");
+
if (!rel)
return NULL;
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
@@ -375,6 +375,8 @@ atom2sql(atom *a)
if (a->data.vtype == TYPE_str && EC_INTERVAL(ec))
ec = EC_STRING;
/* todo handle NULL's early */
+ if (a->isnull)
+ return _STRDUP("NULL");
switch (ec) {
case EC_BIT:
assert( a->data.vtype == TYPE_bit);
@@ -383,11 +385,8 @@ atom2sql(atom *a)
return _STRDUP("false");
case EC_CHAR:
case EC_STRING:
- assert (a->data.vtype == TYPE_str);
- if (a->data.val.sval)
- sprintf(buf, "'%s'", a->data.val.sval);
- else
- sprintf(buf, "NULL");
+ assert(a->data.vtype == TYPE_str && a->data.val.sval);
+ sprintf(buf, "'%s'", a->data.val.sval);
break;
case EC_BLOB:
/* TODO atom to string */
@@ -500,11 +499,8 @@ atom2sql(atom *a)
case EC_DATE:
case EC_TIMESTAMP:
if (a->data.vtype == TYPE_str) {
- if (a->data.val.sval)
- sprintf(buf, "%s '%s'", a->tpe.type->sqlname,
- a->data.val.sval);
- else
- sprintf(buf, "NULL");
+ assert(a->data.val.sval);
+ sprintf(buf, "%s '%s'", a->tpe.type->sqlname,
a->data.val.sval);
}
break;
default:
diff --git a/sql/server/sql_partition.c b/sql/server/sql_partition.c
--- a/sql/server/sql_partition.c
+++ b/sql/server/sql_partition.c
@@ -86,6 +86,11 @@ static void exp_find_table_columns(mvc *
static void
rel_find_table_columns(mvc* sql, sql_rel* rel, sql_table *t, list *cols)
{
+ if (THRhighwater()) {
+ (void) sql_error(sql, 10, SQLSTATE(42000) "query too complex:
running out of stack space");
+ return;
+ }
+
if (!rel)
return;
@@ -134,6 +139,11 @@ rel_find_table_columns(mvc* sql, sql_rel
static void
exp_find_table_columns(mvc *sql, sql_exp *e, sql_table *t, list *cols)
{
+ if (THRhighwater()) {
+ (void) sql_error(sql, 10, SQLSTATE(42000) "query too complex:
running out of stack space");
+ return;
+ }
+
if (!e)
return;
switch(e->type) {
@@ -208,11 +218,8 @@ exp_find_table_columns(mvc *sql, sql_exp
}
static str
-find_expression_type(sql_exp *e, sql_subtype *tpe, char *query)
+find_expression_type(sql_exp *e, sql_subtype *tpe)
{
- if (!e)
- throw(SQL,"sql.partition", SQLSTATE(42000) "It was not possible
to compile the expression: '%s'", query);
-
switch(e->type) {
case e_convert: {
assert(list_length(e->r) == 2);
@@ -225,14 +232,16 @@ find_expression_type(sql_exp *e, sql_sub
} else if (e->r) {
*tpe = e->tpe;
} else if (e->f) {
- throw(SQL,"sql.partition", SQLSTATE(42000) "The
expression should return 1 value only");
+ throw(SQL,"sql.partition", SQLSTATE(42000)
"List of values not allowed in expressions");
+ } else {
+ throw(SQL,"sql.partition", SQLSTATE(42000)
"Variables/parameters are not allowed in expressions");
}
} break;
case e_func: {
sql_subfunc *f = e->f;
sql_func *func = f->func;
- if(list_length(func->res) != 1)
- throw(SQL,"sql.partition", SQLSTATE(42000) "The
expression should return 1 value only");
+ if (list_length(func->res) != 1)
+ throw(SQL,"sql.partition", SQLSTATE(42000) "An
expression should return a single value");
*tpe = *(sql_subtype *)f->res->h->data;
} break;
case e_cmp: {
@@ -243,9 +252,9 @@ find_expression_type(sql_exp *e, sql_sub
*tpe = e->tpe;
} break;
case e_psm:
- throw(SQL,"sql.partition", SQLSTATE(42000) "PSM calls
not supported in expressions");
+ throw(SQL,"sql.partition", SQLSTATE(42000) "PSM calls
are not allowed in expressions");
case e_aggr:
- throw(SQL,"sql.partition", SQLSTATE(42000) "Aggregation
functions not supported in expressions");
+ throw(SQL,"sql.partition", SQLSTATE(42000) "Aggregation
functions are not allowed in expressions");
}
return NULL;
}
@@ -262,6 +271,9 @@ bootstrap_partition_expression(mvc* sql,
assert(isPartitionedByExpressionTable(mt));
+ if (sql->emode == m_prepare)
+ throw(SQL,"sql.partition", SQLSTATE(42000) "Partition
expressions not compilable with prepared statements");
+
r = rel_basetable(sql, mt, mt->base.name);
query = mt->part.pexp->exp;
if((exp = rel_parse_val(sql, sa_message(sql->sa, "select %s;", query),
sql->emode, r)) == NULL) {
@@ -278,7 +290,7 @@ bootstrap_partition_expression(mvc* sql,
mt->part.pexp->cols = sa_list(rsa);
exp_find_table_columns(sql, exp, mt, mt->part.pexp->cols);
- if((msg = find_expression_type(exp, &(mt->part.pexp->type), query)) !=
NULL)
+ if((msg = find_expression_type(exp, &(mt->part.pexp->type))) != NULL)
return msg;
sql_ec = mt->part.pexp->type.type->eclass;
@@ -289,7 +301,7 @@ bootstrap_partition_expression(mvc* sql,
throw(SQL, "sql.partition", SQLSTATE(HY001)
MAL_MALLOC_FAIL);
} else {
msg = createException(SQL, "sql.partition",
-
SQLSTATE(42000) "Column type %s not yet supported for the expression return
value", err);
+
SQLSTATE(42000) "Column type %s not supported for the expression return value",
err);
GDKfree(err);
}
}
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
@@ -360,6 +360,9 @@ char *symbol2string(mvc *sql, symbol *se
_DELETE(l);
break;
}
+ case SQL_PARAMETER:
+ strcpy(buf,"?");
+ break;
case SQL_NULL:
strcpy(buf,"NULL");
break;
@@ -414,7 +417,7 @@ char *symbol2string(mvc *sql, symbol *se
*err = e;
}
return NULL;
- }
+ }
case SQL_CAST: {
dlist *dl = se->data.lval;
char *val;
@@ -436,7 +439,6 @@ char *symbol2string(mvc *sql, symbol *se
}
case SQL_AGGR:
case SQL_SELECT:
- case SQL_PARAMETER:
case SQL_CASE:
case SQL_COALESCE:
case SQL_NULLIF:
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list