44ccfacbe3a3d4b300f80d48651c77837a4b571e
galt
  Tue Apr 26 11:12:02 2022 -0700
SQL INJECTION Prevention Version 2 - this improves our methods by making subclauses of SQL that get passed around be both easy and correct to use. The way that was achieved was by getting rid of the obscure and not well used functions sqlSafefFrag and sqlDyStringPrintfFrag and replacing them with the plain versions of those functions, since these are not needed anymore. The new version checks for NOSQLINJ in unquoted %-s which is used to include SQL clauses, and will give an error the NOSQLINJ clause is not present, and this will automatically require the correct behavior by developers. sqlDyStringPrint is a very useful function, however because it was not enforced, users could use various other dyString functions and they operated without any awareness or checking for SQL correct use. Now those dyString functions are prohibited and it will produce an error if you try to use a dyString function on a SQL string, which is simply detected by the presence of the NOSQLINJ prefix.

diff --git src/hg/hgTracks/simpleTracks.c src/hg/hgTracks/simpleTracks.c
index f035b2c..bfe7b63 100644
--- src/hg/hgTracks/simpleTracks.c
+++ src/hg/hgTracks/simpleTracks.c
@@ -865,31 +865,31 @@
 /* Return + or - in place of 1 or -1 */
 {
 if (orient < 0)
     return '-';
 if (orient > 0)
     return '+';
 return '.';
 }
 
 
 struct dyString *uiStateUrlPart(struct track *toggleGroup)
 /* Return a string that contains all the UI state in CGI var
  * format.  If toggleGroup is non-null the visibility of that
  * track will be toggled in the string. */
 {
-struct dyString *dy = newDyString(512);
+struct dyString *dy = dyStringNew(512);
 
 dyStringPrintf(dy, "%s=%s", cartSessionVarName(), cartSessionId(cart));
 if (toggleGroup != NULL && tdbIsCompositeChild(toggleGroup->tdb))
     {
     int vis = toggleGroup->visibility;
     struct trackDb *tdbParent = tdbGetComposite(toggleGroup->tdb);
     char *parentName = tdbParent->track;
     // Find parent track (as opposed to trackDb)
     struct track *tgParent =toggleGroup->parent;
     char *encodedTableName = cgiEncode(parentName);
     char *view = NULL;
     boolean setView = subgroupFind(toggleGroup->tdb,"view",&view);
     if (tgParent!=NULL&& tgParent->visibility != tvHide && tvCompare(tgParent->visibility,vis) > 0)
         {
         setView = FALSE; // Must open parent to see opened child
@@ -1044,64 +1044,64 @@
     char *newPos = disguisePositionVirtSingleChrom(pos); // DISGUISE POS
     safef(pos,sizeof(pos),"%s", newPos);
     freeMem(newPos);
     }
 
 if (theImgBox && curImgTrack)
     {
     char link[512];
     safef(link,sizeof(link),"%s?position=%s&%s",       // NOTE: position may need removing
           hgTracksName(), pos, ui->string);    //       due to portal
     if (!revCmplDisp && x < fullInsideX)  // Do not toggle on side label!
         {
         width -= (fullInsideX+1 - x);
         if (width <= 1)
             {
-            freeDyString(&ui);
+            dyStringFree(&ui);
             return;
             }
         x = fullInsideX+1;
         }
     else if (revCmplDisp && (x+width) >= fullInsideWidth)
         {
         width -= (x+width) - fullInsideWidth + 1;
         if (width <= 1)
             {
-            freeDyString(&ui);
+            dyStringFree(&ui);
             return;
             }
         }
     //#ifdef IMAGEv2_SHORT_MAPITEMS
     //  if (x < insideX && x+width > insideX)
     //      warn("mapBoxReinvoke(%s) map item spanning slices. LX:%d TY:%d RX:%d BY:%d  link:[%s]",
     //           hStringFromTv(toggleGroup->visibility),x, y, x+width, y+height, link);
     //#endif//def IMAGEv2_SHORT_MAPITEMS
     imgTrackAddMapItem(curImgTrack,link,(char *)(message != NULL?message:NULL),x, y, x+width,
                        y+height, track ? track->track : NULL);
     }
 else
     {
     hPrintf("<AREA SHAPE=RECT COORDS=\"%d,%d,%d,%d\" ", x, y, x+width, y+height);
     hPrintf("HREF=\"%s?position=%s",
             hgTracksName(), pos);
     hPrintf("&%s\"", ui->string);
     if (message != NULL)
         mapStatusMessage("%s", message);
     hPrintf("%s>\n", dyStringContents(id));
     }
-freeDyString(&ui);
-freeDyString(&id);
+dyStringFree(&ui);
+dyStringFree(&id);
 }
 
 void mapBoxToggleVis(struct hvGfx *hvg, int x, int y, int width, int height,
                      struct track *curGroup)
 /* Print out image map rectangle that would invoke this program again.
  * program with the current track expanded. */
 {
 char buf[256];
 if (tdbIsCompositeChild(curGroup->tdb))
     safef(buf, sizeof(buf),"Click to alter the display density of %s and similar subtracks",
           curGroup->shortLabel);
 else if (tdbIsComposite(curGroup->tdb))
     safef(buf, sizeof(buf),"Click to alter the maximum display mode density for all %s subtracks",
           curGroup->shortLabel);
 else
@@ -1115,31 +1115,31 @@
 /* Print out image map rectangle that would invoke this program again
  * at a different window. */
 {
 mapBoxReinvoke(hvg, x, y, width, height, track, FALSE, newChrom, newStart, newEnd,
 	       message, NULL);
 
 }
 
 char *hgcNameAndSettings()
 /* Return path to hgc with variables to store UI settings. */
 {
 static struct dyString *dy = NULL;
 
 if (dy == NULL)
     {
-    dy = newDyString(128);
+    dy = dyStringNew(128);
     dyStringPrintf(dy, "%s?%s", hgcName(), cartSidUrlString(cart));
     }
 return dy->string;
 }
 
 void mapBoxHgcOrHgGene(struct hvGfx *hvg, int start, int end, int x, int y, int width, int height,
                        char *track, char *item, char *statusLine, char *directUrl, boolean withHgsid,
                        char *extra)
 /* Print out image map rectangle that would invoke the hgc (human genome click)
  * program. */
 {
 struct dyString *id = dyStringNew(0);
 if (x < 0) x = 0;
 x = hvGfxAdjXW(hvg, x, width);
 int xEnd = x+width;
@@ -1193,31 +1193,31 @@
             hPrintf("HREF=\"%s&o=%d&t=%d&g=%s&i=%s&c=%s&l=%d&r=%d&db=%s&pix=%d",
                 hgcNameAndSettings(), start, end, encodedTrack, encodedItem,
                     chromName, winStart, winEnd,
                     database, tl.picWidth);
             }
         if (extra != NULL)
             hPrintf("&%s", extra);
         hPrintf("\" ");
         if (statusLine != NULL)
             mapStatusMessage("%s", statusLine);
         hPrintf("%s>\n", dyStringContents(id));
         }
     freeMem(encodedItem);
     freeMem(encodedTrack);
     }
-freeDyString(&id);
+dyStringFree(&id);
 }
 
 void mapBoxHc(struct hvGfx *hvg, int start, int end, int x, int y, int width, int height,
               char *track, char *item, char *statusLine)
 /* Print out image map rectangle that would invoke the hgc (human genome click)
  * program. */
 {
 mapBoxHgcOrHgGene(hvg, start, end, x, y, width, height, track, item, statusLine, NULL, FALSE, NULL);
 }
 
 double scaleForPixels(double pixelWidth)
 /* Return what you need to multiply bases by to
  * get to scale of pixel coordinates. */
 {
 return pixelWidth / (winEnd - winStart);
@@ -1936,31 +1936,33 @@
 
 if (!cartVarExists(cart, "gvDisclaimer"))
     {
     /* display disclaimer and add flag to cart, program exits from here */
     gvDisclaimer();
     }
 else if (sameString("Disagree", cartString(cart, "gvDisclaimer")))
     {
     /* hide track, remove from cart so will get option again later */
     tg->visibility = tvHide;
     cartRemove(cart, "gvDisclaimer");
     cartSetString(cart, "gvPos", "hide");
     return;
     }
 /* load as linked list once, outside of loop */
-srcList = gvSrcLoadByQuery(conn, NOSQLINJ "select * from hgFixed.gvSrc");
+char query[1024];
+sqlSafef(query, sizeof query, "select * from hgFixed.gvSrc");
+srcList = gvSrcLoadByQuery(conn, query);
 /* load part need from gv table, outside of loop (load in hash?) */
 sr = hRangeQuery(conn, tg->table, chromName, winStart, winEnd, NULL, &rowOffset);
 while ((row = sqlNextRow(sr)) != NULL)
     {
     struct gv *details = NULL;
     char query[256];
     struct gvPos *el = gvPosLoad(row);
     sqlSafef(query, sizeof(query), "select * from hgFixed.gv where id = '%s'", el->name);
     details = gvLoadByQuery(conn2, query);
     /* searched items are always visible */
     if (hgFindMatches != NULL && hashIntValDefault(hgFindMatches, el->name, 0) == 1)
         slAddHead(&list, el);
     else if (!gvFilterType(details))
         gvPosFree(&el);
     else if (!gvFilterLoc(details))
@@ -3121,31 +3123,31 @@
     freeMem(vr);
     }
 
 freeHash(&hash);
 
 }
 
 enum {blackShadeIx=9,whiteShadeIx=0};
 
 char *getScoreFilterClause(struct cart *cart,struct trackDb *tdb,char *scoreColumn)
 // Returns "score >= ..." extra where clause if one is needed
 {
 if (scoreColumn == NULL)
     scoreColumn = "score";
 
-struct dyString *extraWhere = newDyString(128);
+struct dyString *extraWhere = dyStringNew(128);
 boolean and = FALSE;
 // gets trackDb 'filterBy' clause, which may filter by 'score', 'name', etc
 extraWhere = dyAddFilterByClause(cart,tdb,extraWhere,NULL,&and);
 extraWhere = dyAddAllScoreFilters(cart,tdb,extraWhere,&and); // All *Filter style filters
 if (and == FALSE      // Cannot have both 'filterBy' score and 'scoreFilter'
 ||  strstrNoCase(extraWhere->string,"score in ") == NULL)
     extraWhere = dyAddFilterAsInt(cart,tdb,extraWhere,SCORE_FILTER,"0:1000",scoreColumn,&and);
 if (sameString(extraWhere->string, ""))
     return NULL;
 return dyStringCannibalize(&extraWhere);
 }
 
 
 void loadLinkedFeaturesWithLoaders(struct track *tg, struct slList *(*itemLoader)(char **row),
                                    struct linkedFeatures *(*lfFromWhatever)(struct slList *item),
@@ -3157,33 +3159,33 @@
 {
 struct sqlConnection *conn = hAllocConn(database);
 struct sqlResult *sr = NULL;
 char **row;
 int rowOffset;
 struct linkedFeatures *lfList = NULL;
 char extraWhere[256] ;
 /* Use tg->tdb->track because subtracks inherit composite track's tdb
  * by default, and the variable is named after the composite track. */
 if ((scoreColumn != NULL) && (cartVarExistsAnyLevel(cart, tg->tdb, FALSE, SCORE_FILTER)))
     {
     char *scoreFilterClause = getScoreFilterClause(cart, tg->tdb,scoreColumn);
     if (scoreFilterClause != NULL)
         {
         if (moreWhere)
-            safef(extraWhere, sizeof(extraWhere), "%s and %s", scoreFilterClause, moreWhere);
+            sqlSafef(extraWhere, sizeof(extraWhere), "%-s and %-s", scoreFilterClause, moreWhere);
         else
-            safef(extraWhere, sizeof(extraWhere), "%s", scoreFilterClause);
+            sqlSafef(extraWhere, sizeof(extraWhere), "%-s", scoreFilterClause);
         freeMem(scoreFilterClause);
         sr = hRangeQuery(conn, tg->table, chromName, winStart, winEnd, extraWhere, &rowOffset);
         }
     }
 else
     sr = hRangeQuery(conn, tg->table, chromName, winStart, winEnd, moreWhere, &rowOffset);
 while ((row = sqlNextRow(sr)) != NULL)
     {
     struct slList *item = itemLoader(row + rowOffset);
     if ((itemFilter == NULL) || (itemFilter(item) == TRUE))
 	{
 	struct linkedFeatures *lf = lfFromWhatever(item);
 	slAddHead(&lfList, lf);
 	}
     }
@@ -5209,31 +5211,31 @@
 char **row, rest[64];
 int rowOffset, i;
 struct linkedFeaturesSeries *lfs;
 struct linkedFeatures *lfList = NULL, *lf;
 
 AllocVar(lfs);
 lfs->name = cloneString(lfsbed->name);
 lfs->start = lfsbed->chromStart;
 lfs->end = lfsbed->chromEnd;
 lfs->orientation = orientFromChar(lfsbed->strand[0]);
 
 /* Get linked features */
 for (i = 0; i < lfsbed->lfCount; i++)
     {
     AllocVar(lf);
-    sqlSafefFrag(rest, sizeof rest, "qName = '%s'", lfsbed->lfNames[i]);
+    sqlSafef(rest, sizeof rest, "qName = '%s'", lfsbed->lfNames[i]);
 
     // use psl table from trackDb, if specified there
     char *pslTable = lfsbed->pslTable;
     if (tdbPslTable != NULL)
         pslTable = tdbPslTable;
 
     sr = hRangeQuery(conn, pslTable, lfsbed->chrom, lfsbed->lfStarts[i],
                      lfsbed->lfStarts[i] + lfsbed->lfSizes[i], rest, &rowOffset);
     if ((row = sqlNextRow(sr)) != NULL)
         {
         struct psl *psl = pslLoad(row+rowOffset);
 	lf = lfFromPsl(psl, FALSE);
 	slAddHead(&lfList, lf);
 	}
     sqlFreeResult(&sr);
@@ -5349,31 +5351,31 @@
 	if (sameWord(optionNot,"include"))
 	    {
 	    sqlDyStringPrintf(query, "%s.name=polyGenotype.name and "
 		"polyGenotype.ethnicGroup=\"%s\" and ",
 		    tg->table, option);
 	    }
 	    else
 	    {
 	    sqlDyStringPrintf(query, "%s.name=polyGenotype.name and "
 		"polyGenotype.ethnicGroup!=\"%s\" and ",
 		    tg->table, option);
 	    }
 	}
     if ((freqLow > 0.0) || (freqHi < 1.0))
 	{
-	    dyStringPrintf(query,
+	    sqlDyStringPrintf(query,
 		"polyGenotype.alleleFrequency>=\"%.1f\" and "
 		    "polyGenotype.alleleFrequency<=\"%.1f\" and ",
 			freqLow, freqHi);
 	}
     }
 else
     {
     sqlDyStringPrintf(query, "select * from %s where ", tg->table);
     }
 
 hAddBinToQuery(winStart, winEnd, query);
 sqlDyStringPrintf(query,
     "chrom=\"%s\" AND chromStart<%d AND chromEnd>%d ",
     chromName, winEnd, winStart);
 
@@ -5391,49 +5393,50 @@
     if (sameWord(option,"yes"))
 	which = ucsc;
     else
 	which = other;
     sqlDyStringPrintf(query, " and polySource=\"%s\"", which);
     }
 
 option = cartCgiUsualString(cart, POLY_SUBFAMILY, POLY_SUBFAMILY_DEFAULT);
 if (differentString(option,POLY_SUBFAMILY_DEFAULT))
     sqlDyStringPrintf(query, " and polySubfamily=\"%s\"", option);
 
 option = cartCgiUsualString(cart, dbRIP_DISEASE, DISEASE_DEFAULT);
 if (differentString(option,DISEASE_DEFAULT))
     {
     if (sameWord(option,"no"))
-	dyStringPrintf(query, " and disease=\"NA\"");
+	sqlDyStringPrintf(query, " and disease=\"NA\"");
     else
-	dyStringPrintf(query, " and disease!=\"NA\"");
+	sqlDyStringPrintf(query, " and disease!=\"NA\"");
     }
 
 sqlDyStringPrintf(query, " group by %s.name", tg->table);
 
-sr = sqlGetResult(conn, dyStringCannibalize(&query));
+sr = sqlGetResult(conn, query->string);
 rowOffset=1;
 
 while ((row = sqlNextRow(sr)) != NULL)
     {
     loadItem = dbRIPLoad(row+rowOffset);
     slAddHead(&itemList, loadItem);
     }
 sqlFreeResult(&sr);
 hFreeConn(&conn);
 slSort(&itemList, bedCmp);
 tg->items = itemList;
+dyStringFree(&query);
 }
 
 static void atomDrawSimpleAt(struct track *tg, void *item,
                              struct hvGfx *hvg, int xOff, int y,
                              double scale, MgFont *font, Color color, enum trackVisibility vis);
 
 int atomTotalHeight(struct track *tg, enum trackVisibility vis)
 /* Most fixed height track groups will use this to figure out the height
  * they use. */
 {
 return tgFixedTotalHeightOptionalOverflow(tg,vis, 6*8, 6*8, FALSE);
 }
 
 int atomItemHeight(struct track *tg, void *item)
 /* Return item height for fixed height track. */
@@ -5659,32 +5662,33 @@
 char varName[SMALLBUF];
 safef(varName, sizeof(varName), "%s.%s", table, HIDE_NONCODING_SUFFIX);
 boolean hideNoncoding = cartUsualBoolean(cart, varName, HIDE_NONCODING_DEFAULT);  // TODO: Use cartUsualBooleanClosestToHome if tableName == tg->tdb->track
 boolean doNmd = FALSE;
 char buff[256];
 safef(buff, sizeof(buff), "hgt.%s.nmdFilter",  tg->track);
 
 /* Should we remove items that appear to be targets for nonsense
  * mediated decay? */
 if(nmdTrackFilter)
     doNmd = cartUsualBoolean(cart, buff, FALSE);
 
 if (tg->itemAttrTbl != NULL)
     itemAttrTblLoad(tg->itemAttrTbl, conn, chrom, start, end);
 
-char *noncodingClause = (hideNoncoding ? "cdsStart != cdsEnd" : NULL);
-gpr = genePredReaderRangeQuery(conn, table, chrom, start, end, noncodingClause);
+char noncodingClause[12024];
+sqlSafef(noncodingClause, sizeof noncodingClause, "cdsStart != cdsEnd");
+gpr = genePredReaderRangeQuery(conn, table, chrom, start, end, hideNoncoding ? noncodingClause : NULL);
 while ((gp = genePredReaderNext(gpr)) != NULL)
     {
     if (doNmd && genePredNmdTarget(gp))
 	{
 	genePredFree(&gp);
 	}
     else
         {
         slAddHead(&lfList, linkedFeaturesFromGenePred(tg, gp, extra));
         }
     }
 slReverse(&lfList);
 genePredReaderFree(&gpr);
 
 if (tg->visibility != tvDense)
@@ -6035,46 +6039,46 @@
 boolean useProtDisplayId = sameString(hg17KgLabel, "UniProt Display ID")
     || sameString(hg17KgLabel, "all");
 
 boolean useMimId = sameString(hg17KgLabel, "OMIM ID")
     || sameString(hg17KgLabel, "all");
 
 boolean useAll = sameString(hg17KgLabel, "all");
 
 if (hTableExists(database, "kgXref"))
     {
     for (lf = lfList; lf != NULL; lf = lf->next)
 	{
         struct dyString *name = dyStringNew(SMALLDYBUF);
         if (useGeneSymbol)
             {
-            sqlSafefFrag(cond_str, sizeof cond_str, "kgID='%s'", lf->name);
+            sqlSafef(cond_str, sizeof cond_str, "kgID='%s'", lf->name);
             geneSymbol = sqlGetField("hg17", "kgXref", "geneSymbol", cond_str);
             if (geneSymbol != NULL)
                 {
                 dyStringAppend(name, geneSymbol);
                 if (useAll) dyStringAppendC(name, '/');
                 }
             }
         if (useKgId)
             {
             dyStringAppend(name, lf->name);
             if (useAll) dyStringAppendC(name, '/');
 	    }
         if (useProtDisplayId)
             {
-	    sqlSafefFrag(cond_str, sizeof(cond_str), "kgID='%s'", lf->name);
+	    sqlSafef(cond_str, sizeof(cond_str), "kgID='%s'", lf->name);
             protDisplayId = sqlGetField("hg17", "kgXref", "spDisplayID", cond_str);
             dyStringAppend(name, protDisplayId);
 	    }
         if (useMimId && sqlTableExists(conn, refLinkTable))
             {
             sqlSafef(cond_str, sizeof(cond_str), "select cast(r.omimId as char) from kgXref,%s r where kgID = '%s' and kgXref.refseq = r.mrnaAcc and r.omimId != 0",refLinkTable, lf->name);
             mimId = sqlQuickString(conn, cond_str);
             if (mimId)
                 dyStringAppend(name, mimId);
             }
         lf->extra = dyStringCannibalize(&name);
 	}
     }
 hFreeConn(&conn);
 }
@@ -6200,89 +6204,89 @@
     for (lf = lfList; lf != NULL; lf = lf->next)
 	{
         struct dyString *name = dyStringNew(SMALLDYBUF);
         struct knownGenesExtra *kgE;
         struct genePredExt *gp = lf->original;
         AllocVar(kgE);
         labelStarted = FALSE; /* reset between items */
         if (useGeneSymbol)
             {
             if ( isBigGenePred )
                 {
                 geneSymbol = gp->geneName;
                 }
             else
                 {
-                sqlSafefFrag(cond_str, sizeof cond_str,"kgID='%s'", lf->name);
+                sqlSafef(cond_str, sizeof cond_str,"kgID='%s'", lf->name);
                 geneSymbol = sqlGetField(database, "kgXref", "geneSymbol", cond_str);
                 }
             if (geneSymbol != NULL)
                 {
                 dyStringAppend(name, geneSymbol);
                 }
             labelStarted = TRUE;
             }
         if (useGencodeId)
             {
             if (labelStarted) dyStringAppendC(name, '/');
             else labelStarted = TRUE;
             if ( isBigGenePred )
                 {
                 gencodeId = isGencode2 ? gp->name : gp->name2;
                 }
             else
                 {
                 if (isGencode2)
                     gencodeId = lf->name;
                 else
                     {
-                    sqlSafefFrag(cond_str, sizeof(cond_str), "name='%s'", lf->name);
+                    sqlSafef(cond_str, sizeof(cond_str), "name='%s'", lf->name);
                     gencodeId = sqlGetField(database, "knownGene", "alignID", cond_str);
                     }
                 }
 	    dyStringAppend(name, gencodeId);
 	    }
         if (useKgId)
             {
             if (labelStarted) dyStringAppendC(name, '/');
             else labelStarted = TRUE;
             if (isGencode2)
                 {
-                sqlSafefFrag(cond_str, sizeof(cond_str), "name='%s'", lf->name);
+                sqlSafef(cond_str, sizeof(cond_str), "name='%s'", lf->name);
                 char *ucId = sqlGetField(database, "knownGene", "alignID", cond_str);
                 dyStringAppend(name, ucId);
                 }
             else
                 dyStringAppend(name, lf->name);
             }
         if (useProtDisplayId)
             {
             if (labelStarted) dyStringAppendC(name, '/');
             else labelStarted = TRUE;
             if ( isBigGenePred )
                 {
                 dyStringAppend(name, gp->geneName2);
                 }
             else
                 {
                 if (lf->extra != NULL)
                     {
                     dyStringAppend(name, (char *)lf->extra);
                     }
                 else
                     {
-                    sqlSafefFrag(cond_str, sizeof(cond_str), "kgID='%s'", lf->name);
+                    sqlSafef(cond_str, sizeof(cond_str), "kgID='%s'", lf->name);
                     protDisplayId = sqlGetField(database, "kgXref", "spDisplayID", cond_str);
                     dyStringAppend(name, protDisplayId);
                     }
                 }
 	    }
         if (useMimId && sqlTableExists(conn, refLinkTable))
             {
             if (labelStarted) dyStringAppendC(name, '/');
             else labelStarted = TRUE;
             sqlSafef(cond_str, sizeof(cond_str), "select cast(r.omimId as char) from kgXref,%s r where kgID = '%s' and kgXref.refseq = r.mrnaAcc and r.omimId != 0",refLinkTable, lf->name);
             mimId = sqlQuickString(conn, cond_str);
             if (mimId)
                 dyStringAppend(name, mimId);
             }
         /* should this be a hash instead? */
@@ -6484,71 +6488,71 @@
         Lightest blue:  Eveything else
 */
 
 lighter.r = (6*normal->r + 4*255) / 10;
 lighter.g = (6*normal->g + 4*255) / 10;
 lighter.b = (6*normal->b + 4*255) / 10;
 
 lightest.r = (1*normal->r + 2*255) / 3;
 lightest.g = (1*normal->g + 2*255) / 3;
 lightest.b = (1*normal->b + 2*255) / 3;
 
 /* set default to the lightest color */
 col = hvGfxFindColorIx(hvg, lightest.r, lightest.g, lightest.b);
 
 /* set color first according to RefSeq status (if there is a corresponding RefSeq) */
-sqlSafefFrag(cond_str, sizeof cond_str, "name='%s' ", lf->name);
+sqlSafef(cond_str, sizeof cond_str, "name='%s' ", lf->name);
 refAcc = sqlGetField(database, "refGene", "name", cond_str);
 if (refAcc != NULL)
     {
     if (sqlTableExists(conn, refSeqStatusTable))
         {
         sqlSafef(query, sizeof query, "select status from %s where mrnaAcc = '%s'", refSeqStatusTable, refAcc);
         sr = sqlGetResult(conn, query);
         if ((row = sqlNextRow(sr)) != NULL)
             {
 	    if (startsWith("Reviewed", row[0]) || startsWith("Validated", row[0]))
                 {
                 /* Use the usual color */
                 col = tg->ixColor;
                 }
 	    else
                 {
                 col = hvGfxFindColorIx(hvg, lighter.r, lighter.g, lighter.b);
                 }
 	    }
 	sqlFreeResult(&sr);
 	}
     }
 
 /* set to dark blue if there is a corresponding Swiss-Prot protein */
-sqlSafefFrag(cond_str, sizeof cond_str, "name='%s'", lf->name);
+sqlSafef(cond_str, sizeof cond_str, "name='%s'", lf->name);
 proteinID= sqlGetField(database, "knownGene", "proteinID", cond_str);
 if (proteinID != NULL && protDbName != NULL)
     {
-    sqlSafefFrag(cond_str, sizeof cond_str, "displayID='%s' AND biodatabaseID=1 ", proteinID);
+    sqlSafef(cond_str, sizeof cond_str, "displayID='%s' AND biodatabaseID=1 ", proteinID);
     ans= sqlGetField(protDbName, "spXref3", "displayID", cond_str);
     if (ans != NULL)
         {
         col = tg->ixColor;
         }
     }
 
 /* if a corresponding PDB entry exists, set it to black */
 if (protDbName != NULL)
     {
-    sqlSafefFrag(cond_str, sizeof cond_str, "sp='%s'", proteinID);
+    sqlSafef(cond_str, sizeof cond_str, "sp='%s'", proteinID);
     pdbID= sqlGetField(protDbName, "pdbSP", "pdb", cond_str);
     }
 
 if (pdbID != NULL)
     {
     col = MG_BLACK;
     }
 
 hFreeConn(&conn);
 return(col);
 }
 
 
 Color knownGeneColor(struct track *tg, void *item, struct hvGfx *hvg)
 /* Return color for a known gene item - looking it up in table in
@@ -6795,31 +6799,31 @@
 char **row;
 char query[256];
 char cond_str[256];
 char *decipherId = NULL;
 
 /* So far, we can just remove "chr" from UCSC chrom names to get DECIPHER names */
 char *decipherChrom = bed->chrom;
 if (startsWithNoCase("chr", bed->chrom))
     decipherChrom += 3;
 
 /* color scheme:
 	RED:	If the entry is a deletion (mean ratio < 0)
 	BLUE:	If the entry is a duplication (mean ratio > 0)
 	GREY:	If the entry was not provided with a mean ratio value (or it's 0)
 */
-sqlSafefFrag(cond_str, sizeof(cond_str),"name='%s' ", bed->name);
+sqlSafef(cond_str, sizeof(cond_str),"name='%s' ", bed->name);
 decipherId = sqlGetField(database, "decipher", "name", cond_str);
 if (decipherId != NULL)
     {
     if (hTableExists(database, "decipherRaw"))
         {
         sqlSafef(query, sizeof(query),
               "select mean_ratio from decipherRaw where id = '%s' and "
               "chr = '%s' and start = %d and end = %d",
 	          decipherId, decipherChrom, bed->chromStart+1, bed->chromEnd);
 	sr = sqlGetResult(conn, query);
         if ((row = sqlNextRow(sr)) != NULL)
             {
             if (isEmpty(row[0]) || (atof(row[0]) == 0.0))
                 {
                 col = MG_GRAY;
@@ -6889,31 +6893,31 @@
 char query[256];
 char cond_str[256];
 char *decipherId = NULL;
 
 /* So far, we can just remove "chr" from UCSC chrom names to get DECIPHER names */
 char *decipherChrom = bed->chrom;
 if (startsWithNoCase("chr", bed->chrom))
     decipherChrom += 3;
 
 /* color scheme:
     BLACK:      If the entry is likely or definitely pathogenic
     DARK GRAY:  If the entry is uncertain or unknown
     LIGHT GRAY: If the entry is likely or definitely benign
 */
 
-sqlSafefFrag(cond_str, sizeof(cond_str),"name='%s' ", bed->name);
+sqlSafef(cond_str, sizeof(cond_str),"name='%s' ", bed->name);
 decipherId = sqlGetField(database, "decipherSnvs", "name", cond_str);
 
 if (decipherId != NULL)
     {
     if (hTableExists(database, "decipherSnvsRaw"))
         {
         sqlSafef(query, sizeof(query), "select pathogenicity from decipherSnvsRaw where "
             "id = '%s' and chr = '%s' and start = '%d' and end = '%d'",
             decipherId, decipherChrom, bed->chromStart+1, bed->chromEnd);
 	sr = sqlGetResult(conn, query);
         col = MG_GRAY;
         if ((row = sqlNextRow(sr)) != NULL)
             {
             char *ucPathogenicity = cloneString(row[0]);
             strUpper(ucPathogenicity);
@@ -7000,31 +7004,31 @@
     if (s > e)
 	return;
     int x1 = round((s-winStart)*scale) + xOff;
     int x2 = round((e-winStart)*scale) + xOff;
     int w = x2 - x1;
     if (w < 1)
 	w = 1;
     hvGfxBox(hvg, x1, y, w, heightPer, color);
     if (tg->drawName && vis != tvSquish)
 	{
 	/* get description from rgdQtlLink table */
 	struct sqlConnection *conn = hAllocConn(database);
 	char cond_str[256];
 	char linkTable[256];
 	safef(linkTable, sizeof(linkTable), "%sLink", tg->table);
-	sqlSafefFrag(cond_str, sizeof(cond_str), "name='%s'", tg->itemName(tg, bed));
+	sqlSafef(cond_str, sizeof(cond_str), "name='%s'", tg->itemName(tg, bed));
         char *s = sqlGetField(database, linkTable, "description", cond_str);
 	hFreeConn(&conn);
 	if (s == NULL)
 	    s = bed->name;
 	/* chop off text starting from " (human)" */
 	char *chp = strstr(s, " (human)");
 	if (chp != NULL) *chp = '\0';
 	/* adjust range of text display to fit within the display window */
 	int x3=x1, x4=x2;
 	if (x3 < xOff) x3 = xOff;
 	if (x4 > (insideWidth + xOff)) x4 = insideWidth + xOff;
 	int w2 = x4 - x3;
 	/* calculate how many characters we can squeeze into box */
 	int boxWidth = w2 / mgFontCharWidth(font, 'm');
 	int textWidth = strlen(s);
@@ -8741,36 +8745,36 @@
 }
 
 void cpgIslandMethods(struct track *tg)
 /* Make track for simple repeats. */
 {
 tg->loadItems = loadCpgIsland;
 tg->freeItems = freeCpgIsland;
 tg->itemColor = cpgIslandColor;
 }
 
 char *rgdGeneItemName(struct track *tg, void *item)
 /* Return name of RGD gene track item. */
 {
 static char name[32];
 struct sqlConnection *conn = hAllocConn(database);
-struct dyString *ds = newDyString(256);
+struct dyString *ds = dyStringNew(256);
 struct linkedFeatures *lf = item;
 
 sqlDyStringPrintf(ds, "select name from rgdGeneLink where refSeq = '%s'", lf->name);
 sqlQuickQuery(conn, ds->string, name, sizeof(name));
-freeDyString(&ds);
+dyStringFree(&ds);
 hFreeConn(&conn);
 return name;
 }
 
 void rgdGeneMethods(struct track *tg)
 /* Make track for RGD genes. */
 {
 tg->itemName = rgdGeneItemName;
 }
 
 void loadGcPercent(struct track *tg)
 /* Load up simpleRepeats from database table to track items. */
 {
 struct sqlConnection *conn = hAllocConn(database);
 struct sqlResult *sr = NULL;
@@ -9589,31 +9593,31 @@
 Color wgRnaColor(struct track *tg, void *item, struct hvGfx *hvg)
 /* Return color of wgRna track item. */
 {
 char condStr[255];
 char *rnaType;
 Color color = {MG_BLACK};  /* Set default to black.  But, if we got black, something is wrong. */
 Color hColor;
 struct rgbColor hAcaColor = {0, 128, 0}; /* darker green */
 struct sqlConnection *conn;
 char *name;
 
 conn = hAllocConn(database);
 hColor = hvGfxFindColorIx(hvg, hAcaColor.r, hAcaColor.g, hAcaColor.b);
 
 name = tg->itemName(tg, item);
-sqlSafefFrag(condStr, sizeof condStr, "name='%s'", name);
+sqlSafef(condStr, sizeof condStr, "name='%s'", name);
 rnaType = sqlGetField(database, "wgRna", "type", condStr);
 if (sameWord(rnaType, "miRna"))   color = MG_RED;
 if (sameWord(rnaType, "HAcaBox")) color = hColor;
 if (sameWord(rnaType, "CDBox"))   color = MG_BLUE;
 if (sameWord(rnaType, "scaRna"))  color = MG_MAGENTA;
 
 hFreeConn(&conn);
 return(color);
 }
 
 void wgRnaMethods(struct track *tg)
 /* Make track for wgRna. */
 {
 tg->itemColor = wgRnaColor;
 }
@@ -10705,68 +10709,72 @@
                     MgFont *font, Color color, enum trackVisibility vis)
 {
 int baseWidth = seqEnd - seqStart;
 struct repeatItem *cghi;
 int y = yOff;
 int heightPer = tg->heightPer;
 int lineHeight = tg->lineHeight;
 int x1,x2,w;
 boolean isFull = (vis == tvFull);
 Color col;
 struct sqlConnection *conn = hAllocConn(database);
 struct sqlResult *sr = NULL;
 char **row;
 int rowOffset;
 struct cgh cghRecord;
+char where[256];
 
 /* Set up the shades of colors */
 if (!exprBedColorsMade)
     makeRedGreenShades(hvg);
 
 if (isFull)
     {
     /* Create tissue specific average track */
     struct hash *hash = newHash(6);
 
     for (cghi = tg->items; cghi != NULL; cghi = cghi->next)
         {
 	cghi->yOffset = y;
 	y += lineHeight;
 	hashAdd(hash, cghi->class, cghi);
 	}
-    sr = hRangeQuery(conn, "cgh", chromName, winStart, winEnd, "type = 2", &rowOffset);
+    
+    sqlSafef(where, sizeof where, "type = 2");
+    sr = hRangeQuery(conn, "cgh", chromName, winStart, winEnd, where, &rowOffset);
     /* sr = hRangeQuery(conn, "cgh", chromName, winStart, winEnd, "type = 3", &rowOffset); */
     while ((row = sqlNextRow(sr)) != NULL)
         {
 	cghStaticLoad(row+rowOffset, &cghRecord);
         cghi = hashFindVal(hash, cghRecord.tissue);
 	/* cghi = hashFindVal(hash, cghRecord.name); */
 	if (cghi == NULL)
 	   cghi = otherCghItem;
 	col = getExprDataColor((cghRecord.score * -1), 0.7, TRUE);
 	x1 = roundingScale(cghRecord.chromStart-winStart, width, baseWidth)+xOff;
 	x2 = roundingScale(cghRecord.chromEnd-winStart, width, baseWidth)+xOff;
 	w = x2-x1;
 	if (w <= 0)
 	    w = 1;
 	hvGfxBox(hvg, x1, cghi->yOffset, w, heightPer, col);
         }
     freeHash(&hash);
     }
 else
     {
-    sr = hRangeQuery(conn, "cgh", chromName, winStart, winEnd, "type = 1", &rowOffset);
+    sqlSafef(where, sizeof where, "type = 1");
+    sr = hRangeQuery(conn, "cgh", chromName, winStart, winEnd, where, &rowOffset);
     while ((row = sqlNextRow(sr)) != NULL)
         {
 	cghStaticLoad(row+rowOffset, &cghRecord);
 	col = getExprDataColor((cghRecord.score * -1), 0.5, TRUE);
 	x1 = roundingScale(cghRecord.chromStart-winStart, width, baseWidth)+xOff;
 	x2 = roundingScale(cghRecord.chromEnd-winStart, width, baseWidth)+xOff;
 	w = x2-x1;
 	if (w <= 0)
 	  w = 1;
 	hvGfxBox(hvg, x1, yOff, w, heightPer, col);
         }
     }
 sqlFreeResult(&sr);
 hFreeConn(&conn);
 }
@@ -11200,59 +11208,59 @@
 
 char *pgSnpName(struct track *tg, void *item)
 /* Return name of pgSnp track item. */
 {
 struct pgSnp *myItem = item;
 char *copy = cloneString(myItem->name);
 char *name = NULL;
 boolean cmpl = cartUsualBooleanDb(cart, database, COMPLEMENT_BASES_VAR, FALSE);
 if (revCmplDisp)
    cmpl = !cmpl;
 /*complement can't handle the /'s */
 if (cmpl)
     {
     char *list[8];
     int i;
-    struct dyString *ds = newDyString(255);
+    struct dyString *ds = dyStringNew(255);
     i = chopByChar(copy, '/', list, myItem->alleleCount);
     for (i=0; i < myItem->alleleCount; i++)
         {
         complement(list[i], strlen(list[i]));
         if (revCmplDisp)
             reverseComplement(list[i], strlen(list[i]));
         dyStringPrintf(ds, "%s", list[i]);
         if (i != myItem->alleleCount - 1)
             dyStringPrintf(ds, "%s", "/");
         }
     name = cloneString(ds->string);
-    freeDyString(&ds);
+    dyStringFree(&ds);
     }
 else if (revCmplDisp)
     {
     char *list[8];
     int i;
-    struct dyString *ds = newDyString(255);
+    struct dyString *ds = dyStringNew(255);
     i = chopByChar(copy, '/', list, myItem->alleleCount);
     for (i=0; i < myItem->alleleCount; i++)
         {
         reverseComplement(list[i], strlen(list[i]));
         dyStringPrintf(ds, "%s", list[i]);
         if (i != myItem->alleleCount - 1)
             dyStringPrintf(ds, "%s", "/");
         }
     name = cloneString(ds->string);
-    freeDyString(&ds);
+    dyStringFree(&ds);
     }
 /* if no changes needed return bed name */
 if (name == NULL)
     name = cloneString(myItem->name);
 return name;
 }
 
 void pgSnpTextRight(char *display, struct hvGfx *hvg, int x1, int y, int width, int height, Color color, MgFont *font, char *allele, int itemY, int lineHeight)
 /* Put text anchored on right upper corner, doing separate colors if needed. */
 {
 struct hvGfx *hvgWhich = hvg;    // There may be a separate image for sideLabel!
 int textX = x1 - width - 2;
 boolean snapLeft = (textX < fullInsideX);
 if (snapLeft)        /* Snap label to the left. */
     {
@@ -11465,45 +11473,45 @@
 }
 
 void pgSnpMapItem(struct track *tg, struct hvGfx *hvg, void *item,
         char *itemName, char *mapItemName, int start, int end, int x, int y, int width, int height)
 /* create a special map box item with different
  * pop-up statusLine with allele counts
  */
 {
 char *directUrl = trackDbSetting(tg->tdb, "directUrl");
 boolean withHgsid = (trackDbSetting(tg->tdb, "hgsid") != NULL);
 struct pgSnp *el = item;
 char *nameCopy = cloneString(itemName); /* so chopper doesn't mess original */
 char *cntCopy = cloneString(el->alleleFreq);
 char *all[8];
 char *freq[8];
-struct dyString *ds = newDyString(255);
+struct dyString *ds = dyStringNew(255);
 int i = 0;
 chopByChar(nameCopy, '/', all, el->alleleCount);
 if (differentString(el->alleleFreq, ""))
     chopByChar(cntCopy, ',', freq, el->alleleCount);
 
 for (i=0; i < el->alleleCount; i++)
     {
     if (sameString(el->alleleFreq, "") || sameString(freq[i], "0"))
         freq[i] = "?";
     dyStringPrintf(ds, "%s:%s ", all[i], freq[i]);
     }
 mapBoxHgcOrHgGene(hvg, start, end, x, y, width, height, tg->track,
                   mapItemName, ds->string, directUrl, withHgsid, NULL);
-freeDyString(&ds);
+dyStringFree(&ds);
 }
 
 void pgSnpLeftLabels(struct track *tg, int seqStart, int seqEnd,
 		     struct hvGfx *hvg, int xOff, int yOff, int width, int height,
 		     boolean withCenterLabels, MgFont *font, Color color,
 		     enum trackVisibility vis)
 /* pgSnp draws its own left labels when it draws the item in pack or full mode.
  * We don't want the default left labels when in full mode because they can overlap
  * with the item-drawing labels, but we do still need dense mode left labels. */
 {
 if (vis == tvDense)
     {
     if (isCenterLabelIncluded(tg))
 	yOff += mgFontLineHeight(font);
     hvGfxTextRight(hvg, leftLabelX, yOff, leftLabelWidth-1, tg->lineHeight,
@@ -13705,31 +13713,31 @@
 }
 
 void loadVariome(struct track *tg)
 /* Load the items from the variome table (based on wikiTrackLoadItems) */
 {
 struct bed *bed;
 struct sqlConnection *conn = wikiConnect();
 struct sqlResult *sr;
 char **row;
 int rowOffset;
 char where[256];
 struct linkedFeatures *lfList = NULL, *lf;
 int scoreMin = 0;
 int scoreMax = 99999;
 
-sqlSafefFrag(where, ArraySize(where), "db='%s'", database);
+sqlSafef(where, ArraySize(where), "db='%s'", database);
 
 sr = hRangeQuery(conn, tg->table, chromName, winStart, winEnd, where, &rowOffset);
 while ((row = sqlNextRow(sr)) != NULL)
     {
     struct variome *item = variomeLoad(row);
     AllocVar(bed);
     bed->chrom = cloneString(item->chrom);
     bed->chromStart = item->chromStart;
     bed->chromEnd = item->chromEnd;
     bed->name = cloneString(item->name);
     bed->score = item->score;
     safecpy(bed->strand, sizeof(bed->strand), item->strand);
     bed->thickStart = item->chromStart;
     bed->thickEnd = item->chromEnd;
     bed->itemRgb = bedParseRgb(item->color);
@@ -14465,31 +14473,31 @@
 }
 
 void buildMathWig(struct trackDb *tdb)
 /* Turn a mathWig composite into a mathWig track. */
 {
 char *aggregateFunc = cartOrTdbString(cart, tdb, "aggregate" , FALSE);
 
 if ((aggregateFunc == NULL) || !(sameString("add", aggregateFunc) || sameString("subtract", aggregateFunc)))
     return;
 
 struct trackDb *subTracks = tdb->subtracks;
 
 tdb->subtracks = NULL;
 tdb->type = "mathWig";
 
-struct dyString *dy = newDyString(1024);
+struct dyString *dy = dyStringNew(1024);
 
 if (sameString("add", aggregateFunc))
     dyStringPrintf(dy, "+ ");
 else // subtract
     dyStringPrintf(dy, "- ");
 struct trackDb *subTdb;
 for (subTdb=subTracks; subTdb; subTdb = subTdb->next)
     {
     if (!isSubtrackVisibleTdb(cart, subTdb) )
         continue;
 
     char *bigDataUrl = trackDbSetting(subTdb, "bigDataUrl");
     char *useDb;
     char *table;
     if (bigDataUrl != NULL)