080a160c7b9595d516c9c70e83689a09b60839d0 galt Mon Jun 3 12:16:53 2013 -0700 fix SQL Injection diff --git src/hg/hgTracks/pubsTracks.c src/hg/hgTracks/pubsTracks.c index 0c57cd3..655d85b 100644 --- src/hg/hgTracks/pubsTracks.c +++ src/hg/hgTracks/pubsTracks.c @@ -59,31 +59,31 @@ /* assignment of pubs classes to colors */ static struct hash* pubsClassColors = NULL; static void pubsParseClassColors() /* parse class colors from hgFixed.pubsClassColors into the hash pubsClassColors */ { if (pubsClassColors!=NULL) return; pubsClassColors = hashNew(0); struct sqlConnection *conn = hAllocConn(database); if (!sqlTableExists(conn, "hgFixed.pubsClassColors")) { return; } -char *query = "SELECT class, rgbColor FROM hgFixed.pubsClassColors"; +char *query = "NOSQLINJ SELECT class, rgbColor FROM hgFixed.pubsClassColors"; struct sqlResult *sr = sqlGetResult(conn, query); char **row = NULL; while ((row = sqlNextRow(sr)) != NULL) { char *class = row[0]; char *colStr = row[1]; // copied from genePredItemClassColor - is there no function for this? // convert comma sep rgb string to array char *rgbVals[5]; chopString(colStr, ",", rgbVals, sizeof(rgbVals)); struct rgbColor *rgb; AllocVar(rgb); rgb->r = (sqlUnsigned(rgbVals[0])); rgb->g = (sqlUnsigned(rgbVals[1])); rgb->b = (sqlUnsigned(rgbVals[2])); @@ -112,37 +112,37 @@ /* bad solution: a function that is called before the extra field is * accessed and that fills it from a sql query. Will need to redo this like gencode, * drawing from atom, variome and bedLoadN or bedDetails */ { char query[LARGEBUF]; struct sqlResult *sr = NULL; char **row = NULL; struct pubsExtra *extra = NULL; /* support two different storage places for article data: either the bed table directly * includes the title + author of the article or we have to look it up from the articles * table. Having a copy of the title in the bed table is faster */ bool newFormat = FALSE; if (sqlColumnExists(conn, tg->table, "title")) { - safef(query, sizeof(query), "SELECT firstAuthor, year, title, impact, classes FROM %s " + sqlSafef(query, sizeof(query), "SELECT firstAuthor, year, title, impact, classes FROM %s " "WHERE chrom = '%s' and chromStart = '%d' and name='%s'", tg->table, chromName, lf->start, lf->name); newFormat = TRUE; } else { - safef(query, sizeof(query), "SELECT firstAuthor, year, title FROM %s WHERE articleId = '%s'", + sqlSafef(query, sizeof(query), "SELECT firstAuthor, year, title FROM %s WHERE articleId = '%s'", articleTable, lf->name); newFormat = FALSE; } sr = sqlGetResult(conn, query); if ((row = sqlNextRow(sr)) != NULL) { char *firstAuthor = row[0]; char *year = row[1]; char *title = row[2]; char *impact = NULL; char *classes = NULL; extra = needMem(sizeof(struct pubsExtra)); @@ -223,49 +223,49 @@ static void pubsAddExtra(struct track* tg, struct linkedFeatures* lf) /* add authorYear and title to linkedFeatures->extra */ { char *articleTable = trackDbSettingClosestToHome(tg->tdb, "pubsArticleTable"); if(isEmpty(articleTable)) return; if (lf->extra != NULL) return; struct sqlConnection *conn = hAllocConn(database); struct pubsExtra* extra = pubsMakeExtra(tg, articleTable, conn, lf); lf->extra = extra; hFreeConn(&conn); } -static void dyStringPrintfWithSep(struct dyString *ds, char *sep, char *format, ...) +static void sqlDyStringPrintfWithSep(struct dyString *ds, char* sep, char *format, ...) /* Printf to end of dyString. Prefix with sep if dyString is not empty. */ { if (ds->stringSize!=0) dyStringAppend(ds, sep); va_list args; va_start(args, format); -dyStringVaPrintf(ds, format, args); +sqlDyStringVaPrintfFrag(ds, format, args); va_end(args); } struct hash* searchForKeywords(struct sqlConnection* conn, char *articleTable, char *keywords) /* return hash with the articleIds that contain a given keyword in the abstract/title/authors */ { if (isEmpty(keywords)) return NULL; char query[12000]; -safef(query, sizeof(query), "SELECT articleId FROM %s WHERE " +sqlSafef(query, sizeof(query), "SELECT articleId FROM %s WHERE " "MATCH (citation, title, authors, abstract) AGAINST ('%s' IN BOOLEAN MODE)", articleTable, keywords); //printf("query %s", query); struct slName *artIds = sqlQuickList(conn, query); if (artIds==NULL || slCount(artIds)==0) return NULL; // convert list to hash struct hash *hashA = hashNew(0); struct slName *el; for (el = artIds; el != NULL; el = el->next) hashAddInt(hashA, el->name, 1); freeMem(keywords); slFreeList(artIds); return hashA; } @@ -274,67 +274,67 @@ /* load items that fulfill keyword and year filter */ { pubsParseClassColors(); struct sqlConnection *conn = hAllocConn(database); char *keywords = cartOptionalStringClosestToHome(cart, tg->tdb, FALSE, "pubsFilterKeywords"); char *yearFilter = cartOptionalStringClosestToHome(cart, tg->tdb, FALSE, "pubsFilterYear"); char *publFilter = cartOptionalStringClosestToHome(cart, tg->tdb, FALSE, "pubsFilterPublisher"); char *articleTable = pubsArticleTable(tg); if(sameOk(yearFilter, "anytime")) yearFilter = NULL; if(sameOk(publFilter, "all")) publFilter = NULL; if(isNotEmpty(keywords)) - keywords = makeMysqlMatchStr(sqlEscapeString(keywords)); + keywords = makeMysqlMatchStr(keywords); if (isEmpty(yearFilter) && isEmpty(keywords) && isEmpty(publFilter)) { loadGappedBed(tg); } else { // put together an "extra" query to hExtendedRangeQuery that removes articles // without the keywords specified in hgTrackUi char *oldLabel = tg->longLabel; tg->longLabel = catTwoStrings(oldLabel, " (filter activated)"); freeMem(oldLabel); char **row; struct linkedFeatures *lfList = NULL; struct trackDb *tdb = tg->tdb; int scoreMin = atoi(trackDbSettingClosestToHomeOrDefault(tdb, "scoreMin", "0")); int scoreMax = atoi(trackDbSettingClosestToHomeOrDefault(tdb, "scoreMax", "1000")); boolean useItemRgb = bedItemRgb(tdb); char *extra = NULL; struct dyString *extraDy = dyStringNew(0); struct hash *articleIds = searchForKeywords(conn, articleTable, keywords); if (sqlColumnExists(conn, tg->table, "year")) // new table schema: filter fields are on main bed table { if (isNotEmpty(yearFilter)) - dyStringPrintfWithSep(extraDy, " AND ", " year >= '%s'", sqlEscapeString(yearFilter)); + sqlDyStringPrintfWithSep(extraDy, " AND ", " year >= '%s'", yearFilter); if (isNotEmpty(publFilter)) - dyStringPrintfWithSep(extraDy, " AND ", " publisher = '%s'", sqlEscapeString(publFilter)); + sqlDyStringPrintfWithSep(extraDy, " AND ", " publisher = '%s'", publFilter); } else // old table schema, filter by doing a join on article table { if(isNotEmpty(yearFilter)) - dyStringPrintf(extraDy, "name IN (SELECT articleId FROM %s WHERE year>='%s')", articleTable, \ + sqlDyStringPrintfFrag(extraDy, "name IN (SELECT articleId FROM %s WHERE year>='%s')", articleTable, \ yearFilter); } if (extraDy->stringSize > 0) extra = extraDy->string; else extra = NULL; int rowOffset = 0; struct sqlResult *sr = hExtendedRangeQuery(conn, tg->table, chromName, winStart, winEnd, extra, FALSE, NULL, &rowOffset); freeDyString(&extraDy); while ((row = sqlNextRow(sr)) != NULL) @@ -443,44 +443,44 @@ struct bed *bed = item; genericMapItem(tg, hvg, item, bed->name, bed->name, start, end, x, y, width, height); } static struct hash* pubsLookupSequences(struct track *tg, struct sqlConnection* conn, char *articleId, bool getSnippet) /* create a hash with a mapping annotId -> snippet or annotId -> shortSeq for an articleId*/ { char query[LARGEBUF]; char *sequenceTable = trackDbRequiredSetting(tg->tdb, "pubsSequenceTable"); char *selectValSql = NULL; if (getSnippet) selectValSql = "replace(replace(snippet, \"<B>\", \"\\n>>> \"), \"</B>\", \" <<<\\n\")"; else selectValSql = "concat(substr(sequence,1,4),\"...\",substr(sequence,-4))"; - safef(query, sizeof(query), "SELECT annotId, %s FROM %s WHERE articleId='%s' ", + sqlSafef(query, sizeof(query), "SELECT annotId, %s FROM %s WHERE articleId='%s' ", selectValSql, sequenceTable, articleId); struct hash *seqIdHash = sqlQuickHash(conn, query); - //freeMem(sequenceTable); // XX Why does this crash?? + //freeMem(sequenceTable); // XX Why does this crash?? because trackDbRequiredSetting returns a value in a hash. do not free. return seqIdHash; } static char *pubsArticleDispId(struct track *tg, struct sqlConnection *conn, char *articleId) /* given an articleId, lookup author and year and create <author><year> label for it */ { char *dispLabel = NULL; char *articleTable = pubsArticleTable(tg); char query[LARGEBUF]; -safef(query, sizeof(query), "SELECT firstAuthor, year FROM %s WHERE articleId = '%s'", +sqlSafef(query, sizeof(query), "SELECT firstAuthor, year FROM %s WHERE articleId = '%s'", articleTable, articleId); struct sqlResult *sr = sqlGetResult(conn, query); if (sr!=NULL) { char **row = NULL; row = sqlNextRow(sr); if (row != NULL) dispLabel = pubsFeatureLabel(row[0], row[1]); else dispLabel = articleId; } else dispLabel = articleId; sqlFreeResult(&sr); return dispLabel;