Changeset: 09dad7e2d985 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=09dad7e2d985
Added Files:
sql/test/BugTracker-2015/Tests/crash_timestamp_convert.Bug-3816.stable.out.Darwin.src
sql/test/BugTracker-2015/Tests/crash_timestamp_convert.Bug-3816.stable.out.FreeBSD
sql/test/BugTracker-2017/Tests/fullouterjoinfilter.Bug-6256.sql
sql/test/BugTracker-2017/Tests/fullouterjoinfilter.Bug-6256.stable.err
sql/test/BugTracker-2017/Tests/fullouterjoinfilter.Bug-6256.stable.out
sql/test/BugTracker-2017/Tests/wrong_aggregation_count.Bug-6257.sql
sql/test/BugTracker-2017/Tests/wrong_aggregation_count.Bug-6257.stable.err
sql/test/BugTracker-2017/Tests/wrong_aggregation_count.Bug-6257.stable.out
Modified Files:
sql/backends/monet5/sql_execute.c
sql/backends/monet5/sql_scenario.h
sql/backends/monet5/vaults/fits/fits.c
sql/backends/monet5/vaults/netcdf/netcdf.c
sql/test/BugTracker-2015/Tests/schema-trigger.Bug-3710.sql
sql/test/BugTracker-2015/Tests/schema-trigger.Bug-3710.stable.err
sql/test/BugTracker-2015/Tests/schema-trigger.Bug-3710.stable.out
sql/test/BugTracker-2016/Tests/convert-function-test.Bug-3460.stable.out
sql/test/BugTracker-2016/Tests/convert-function-test.Bug-3460.stable.out.int128
sql/test/BugTracker-2017/Tests/All
sql/test/BugTracker-2017/Tests/crash_correlated_subqueries_in_select.Bug-6254.sql
sql/test/BugTracker-2017/Tests/crash_correlated_subqueries_in_select.Bug-6254.stable.out
Branch: default
Log Message:
Merge with Dec2016 branch.
diffs (truncated from 1195 to 300 lines):
diff --git a/sql/backends/monet5/sql_execute.c
b/sql/backends/monet5/sql_execute.c
--- a/sql/backends/monet5/sql_execute.c
+++ b/sql/backends/monet5/sql_execute.c
@@ -352,6 +352,49 @@ SQLrun(Client c, backend *be, mvc *m){
return msg;
}
+/*
+ * Escape single quotes and backslashes. This is important to do before calling
+ * SQLstatementIntern, if we are pasting user provided strings into queries
+ * passed to the SQLstatementIntern. Otherwise we open ourselves to SQL
+ * injection attacks.
+ *
+ * It returns the input string with all the single quotes(') and the
backslashes
+ * (\) doubled, or NULL, if it could not allocate enough space.
+ *
+ * The caller is responsible to free the returned value.
+ */
+str
+SQLescapeString(str s)
+{
+ str ret = NULL;
+ char *p, *q;
+ int len = 0;
+
+ if(!s) {
+ return NULL;
+ }
+
+ /* At most we will need 2*strlen(s) + 1 characters */
+ len = strlen(s);
+ ret = (str)GDKmalloc(2*len + 1);
+ if (!ret) {
+ return NULL;
+ }
+
+ for (p = s, q = ret; *p != '\0'; p++, q++) {
+ *q = *p;
+ if (*p == '\'') {
+ *(++q) = '\'';
+ }
+ else if (*p == '\\') {
+ *(++q) = '\\';
+ }
+ }
+
+ *q = '\0';
+ return ret;
+}
+
str
SQLstatementIntern(Client c, str *expr, str nme, bit execute, bit output,
res_table **result)
{
diff --git a/sql/backends/monet5/sql_scenario.h
b/sql/backends/monet5/sql_scenario.h
--- a/sql/backends/monet5/sql_scenario.h
+++ b/sql/backends/monet5/sql_scenario.h
@@ -43,6 +43,7 @@ sql5_export str SQLstatementIntern(Clien
sql5_export str SQLcompile(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr
pci);
sql5_export str SQLinclude(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr
pci);
sql5_export str SQLCacheRemove(Client c, str nme);
+sql5_export str SQLescapeString(str s);
sql5_export MT_Lock sql_contextLock;
#endif /* _SQL_SCENARIO_H_ */
diff --git a/sql/backends/monet5/vaults/fits/fits.c
b/sql/backends/monet5/vaults/fits/fits.c
--- a/sql/backends/monet5/vaults/fits/fits.c
+++ b/sql/backends/monet5/vaults/fits/fits.c
@@ -31,8 +31,6 @@
#define FITS_INS_COL "INSERT INTO sys.fits_columns(id, name, type, units,
number, table_id) \
VALUES(%d,'%s','%s','%s',%d,%d);"
-#define FILE_INS "INSERT INTO sys.fits_files(id, name) VALUES (%d, '%s');"
-#define DEL_TABLE "DELETE FROM sys.fitsfiles;"
#define ATTACHDIR "call sys.fitsattach('%s');"
static void
@@ -572,14 +570,25 @@ str FITSdir(Client cntxt, MalBlkPtr mb,
s = stmt;
while ((ep = readdir(dp)) != NULL && !msg) {
- snprintf(fname, BUFSIZ, "%s%s", dir, ep->d_name);
+ char *filename = SQLescapeString(ep->d_name);
+ if (!filename) {
+ msg = createException(MAL, "fits.listdir",
MAL_MALLOC_FAIL);
+ break;
+ }
+
+ snprintf(fname, BUFSIZ, "%s%s", dir, filename);
status = 0;
fits_open_file(&fptr, fname, READONLY, &status);
if (status == 0) {
snprintf(stmt, BUFSIZ, ATTACHDIR, fname);
+#ifndef NDEBUG
+ fprintf(stderr, "Executing:\n%s\n", s);
+#endif
msg = SQLstatementIntern(cntxt, &s,
"fits.listofdir", TRUE, FALSE, NULL);
fits_close_file(fptr, &status);
}
+
+ GDKfree(filename);
}
(void)closedir(dp);
} else
@@ -593,6 +602,7 @@ str FITSdirpat(Client cntxt, MalBlkPtr m
str msg = MAL_SUCCEED;
str dir = *getArgReference_str(stk, pci, 1);
str pat = *getArgReference_str(stk, pci, 2);
+ char *filename = NULL;
fitsfile *fptr;
char *s;
int status = 0;
@@ -601,6 +611,7 @@ str FITSdirpat(Client cntxt, MalBlkPtr m
size_t j = 0;
(void)mb;
+
globbuf.gl_offs = 0;
snprintf(fulldirectory, BUFSIZ, "%s%s", dir, pat);
glob(fulldirectory, GLOB_DOOFFS, NULL, &globbuf);
@@ -608,7 +619,7 @@ str FITSdirpat(Client cntxt, MalBlkPtr m
/* fprintf(stderr,"#fulldir: %s \nSize: %lu\n",fulldirectory,
globbuf.gl_pathc);*/
if (globbuf.gl_pathc == 0)
- throw(MAL, "listdir", "Couldn't open the directory or there are
no files that match the pattern");
+ throw(MAL, "fits.listdirpat", "Couldn't open the directory or
there are no files that match the pattern");
for (j = 0; j < globbuf.gl_pathc; j++) {
char stmt[BUFSIZ];
@@ -616,12 +627,21 @@ str FITSdirpat(Client cntxt, MalBlkPtr m
s = stmt;
snprintf(fname, BUFSIZ, "%s", globbuf.gl_pathv[j]);
+ filename = SQLescapeString(fname);
+ if (!filename) {
+ throw(MAL, "fits.listdirpat", MAL_MALLOC_FAIL);
+ }
status = 0;
- fits_open_file(&fptr, fname, READONLY, &status);
+ fits_open_file(&fptr, filename, READONLY, &status);
if (status == 0) {
- snprintf(stmt, BUFSIZ, ATTACHDIR, fname);
+ snprintf(stmt, BUFSIZ, ATTACHDIR, filename);
+ GDKfree(filename);
+#ifndef NDEBUG
+ fprintf(stderr, "Executing:\n%s\n", s);
+#endif
msg = SQLstatementIntern(cntxt, &s,
"fits.listofdirpat", TRUE, FALSE, NULL);
fits_close_file(fptr, &status);
+
break;
}
}
@@ -664,6 +684,7 @@ str FITSattach(Client cntxt, MalBlkPtr m
char tname[BUFSIZ], *tname_low = NULL, *s, bname[BUFSIZ], stmt[BUFSIZ];
long tbcol; /* type long used by fits library */
char cname[BUFSIZ], tform[BUFSIZ], tunit[BUFSIZ], tnull[BUFSIZ],
tdisp[BUFSIZ];
+ char *esc_cname, *esc_tform, *esc_tunit;
double tscal, tzero;
char xtensionname[BUFSIZ] = "", stilversion[BUFSIZ] = "";
char stilclass[BUFSIZ] = "", tdate[BUFSIZ] = "", orig[BUFSIZ] = "",
comm[BUFSIZ] = "";
@@ -807,7 +828,26 @@ str FITSattach(Client cntxt, MalBlkPtr m
cid = store_funcs.count_col(tr, col, 1) + 1;
for (j = 1; j <= cnum; j++, cid++) {
fits_get_acolparms(fptr, j, cname, &tbcol, tunit,
tform, &tscal, &tzero, tnull, tdisp, &status);
- snprintf(stmt, BUFSIZ, FITS_INS_COL, (int)cid, cname,
tform, tunit, j, (int)tid);
+ /* escape the various strings to avoid SQL injection
attacks */
+ esc_cname = SQLescapeString(cname);
+ if (!esc_cname) {
+ throw(MAL, "fits.attach", MAL_MALLOC_FAIL);
+ }
+ esc_tform = SQLescapeString(tform);
+ if (!esc_tform) {
+ GDKfree(esc_cname);
+ throw(MAL, "fits.attach", MAL_MALLOC_FAIL);
+ }
+ esc_tunit = SQLescapeString(tunit);
+ if (!esc_tform) {
+ GDKfree(esc_tform);
+ GDKfree(esc_cname);
+ throw(MAL, "fits.attach", MAL_MALLOC_FAIL);
+ }
+ snprintf(stmt, BUFSIZ, FITS_INS_COL, (int)cid,
esc_cname, esc_tform, esc_tunit, j, (int)tid);
+ GDKfree(esc_tunit);
+ GDKfree(esc_tform);
+ GDKfree(esc_cname);
msg = SQLstatementIntern(cntxt, &s, "fits.attach",
TRUE, FALSE, NULL);
if (msg != MAL_SUCCEED) {
fits_close_file(fptr, &status);
diff --git a/sql/backends/monet5/vaults/netcdf/netcdf.c
b/sql/backends/monet5/vaults/netcdf/netcdf.c
--- a/sql/backends/monet5/vaults/netcdf/netcdf.c
+++ b/sql/backends/monet5/vaults/netcdf/netcdf.c
@@ -232,13 +232,14 @@ NCDFattach(Client cntxt, MalBlkPtr mb, M
size_t dlen, alen;
char dname[NC_MAX_NAME+1], vname[NC_MAX_NAME+1], aname[NC_MAX_NAME +1],
- abuf[80], *aval;
+ abuf[80], *aval;
char **dims = NULL;
nc_type vtype, atype; /* == int */
int retval, avalint;
float avalfl;
double avaldbl;
+ str esc_str0, esc_str1;
msg = getSQLContext(cntxt, mb, &m, NULL);
if (msg)
@@ -278,21 +279,34 @@ header: %s", nc_strerror(retval));
col = mvc_bind_column(m, tfiles, "file_id");
fid = store_funcs.count_col(tr, col, 1) + 1;
- snprintf(buf, BUFSIZ, INSFILE, (int)fid, fname);
+ esc_str0 = SQLescapeString(fname);
+ if (!esc_str0) {
+ msg = createException(MAL, "netcdf.attach", MAL_MALLOC_FAIL);
+ goto finish;
+ }
+ snprintf(buf, BUFSIZ, INSFILE, (int)fid, esc_str0);
+ GDKfree(esc_str0);
if ( ( msg = SQLstatementIntern(cntxt, &s, "netcdf.attach", TRUE,
FALSE, NULL))
- != MAL_SUCCEED )
+ != MAL_SUCCEED )
goto finish;
/* Read dimensions from NetCDF header and insert a row for each one
into netcdf_dims table */
dims = (char **)GDKzalloc(sizeof(char *) * ndims);
for (didx = 0; didx < ndims; didx++){
- if ((retval = nc_inq_dim(ncid, didx, dname, &dlen)))
+ if ((retval = nc_inq_dim(ncid, didx, dname, &dlen)) != 0)
return createException(MAL, "netcdf.attach", "Cannot read
dimension %d : %s", didx, nc_strerror(retval));
- snprintf(buf, BUFSIZ, INSDIM, didx, (int)fid, dname, (int)dlen);
+ esc_str0 = SQLescapeString(dname);
+ if (!esc_str0) {
+ msg = createException(MAL, "netcdf.attach",
MAL_MALLOC_FAIL);
+ goto finish;
+ }
+
+ snprintf(buf, BUFSIZ, INSDIM, didx, (int)fid, esc_str0,
(int)dlen);
+ GDKfree(esc_str0);
if ( ( msg = SQLstatementIntern(cntxt, &s, "netcdf.attach", TRUE,
FALSE, NULL))
- != MAL_SUCCEED )
+ != MAL_SUCCEED )
goto finish;
dims[didx] = GDKstrdup(dname);
@@ -302,24 +316,31 @@ header: %s", nc_strerror(retval));
for (vidx = 0; vidx < nvars; vidx++){
if ( (retval = nc_inq_var(ncid, vidx, vname, &vtype, &vndims,
vdims, &vnatts)))
return createException(MAL, "netcdf.attach",
- "Cannot read variable %d : %s",
- vidx, nc_strerror(retval));
+ "Cannot read
variable %d : %s",
+ vidx,
nc_strerror(retval));
/* Check if this is coordinate variable */
if ( (vndims == 1) && ( strcmp(vname, dims[vdims[0]]) == 0 ))
coord_dim_id = vdims[0];
else coord_dim_id = -1;
- snprintf(buf, BUFSIZ, INSVAR, vidx, (int)fid, vname,
prim_type_name(vtype), vndims, coord_dim_id);
+ esc_str0 = SQLescapeString(vname);
+ if (!esc_str0) {
+ msg = createException(MAL, "netcdf.attach",
MAL_MALLOC_FAIL);
+ goto finish;
+ }
+
+ snprintf(buf, BUFSIZ, INSVAR, vidx, (int)fid, esc_str0,
prim_type_name(vtype), vndims, coord_dim_id);
+ GDKfree(esc_str0);
if ( ( msg = SQLstatementIntern(cntxt, &s, "netcdf.attach", TRUE,
FALSE, NULL))
- != MAL_SUCCEED )
+ != MAL_SUCCEED )
goto finish;
if ( coord_dim_id < 0 ){
for (i = 0; i < vndims; i++){
snprintf(buf, BUFSIZ, INSVARDIM, vidx, vdims[i], (int)fid, i);
if ( ( msg = SQLstatementIntern(cntxt, &s, "netcdf.attach",
TRUE, FALSE, NULL))
- != MAL_SUCCEED )
+ != MAL_SUCCEED )
goto finish;
}
}
@@ -329,62 +350,74 @@ header: %s", nc_strerror(retval));
for (aidx = 0; aidx < vnatts; aidx++){
if ((retval = nc_inq_attname(ncid,vidx,aidx,aname)))
return createException(MAL, "netcdf.attach",
- "Cannot read attribute %d of variable %d: %s",
- aidx, vidx, nc_strerror(retval));
+
"Cannot read attribute %d of variable %d: %s",
+
aidx, vidx, nc_strerror(retval));
- if ((retval = nc_inq_att(ncid,vidx,aname,&atype,&alen)))
+ if ((retval =
nc_inq_att(ncid,vidx,aname,&atype,&alen)))
return createException(MAL, "netcdf.attach",
- "Cannot read attribute %s type and length: %s",
- aname, nc_strerror(retval));
+
"Cannot read attribute %s type and length: %s",
+
aname, nc_strerror(retval));
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list