cc9a51b3c9de74d78a0c7eeedb2b83d6336108c5
max
  Mon Mar 23 04:36:13 2026 -0700
automated code review found that we already have an escape function, so asked Claude to us it, refs #37273

diff --git src/hg/hgc/bigBedClick.c src/hg/hgc/bigBedClick.c
index 23c972f03f3..6df3282ae3c 100644
--- src/hg/hgc/bigBedClick.c
+++ src/hg/hgc/bigBedClick.c
@@ -5,30 +5,31 @@
 
 #include "common.h"
 #include "wiggle.h"
 #include "cart.h"
 #include "hgc.h"
 #include "hCommon.h"
 #include "hgColors.h"
 #include "bigBed.h"
 #include "hui.h"
 #include "subText.h"
 #include "web.h"
 #include "chromAlias.h"
 #include "quickLift.h"
 #include "hgConfig.h"
 #include "jsHelper.h"
+#include "jsonParse.h"
 
 static void bigGenePredLinks(char *track, char *item)
 /* output links to genePred driven sequence dumps */
 {
 printf("<H3>Links to sequence:</H3>\n");
 printf("<UL>\n");
 puts("<LI>\n");
 hgcAnchorSomewhere("htcTranslatedPredMRna", item, "translate", seqName);
 printf("Translated Protein</A> from genomic DNA\n");
 puts("</LI>\n");
 
 puts("<LI>\n");
 hgcAnchorSomewhere("htcGeneMrna", item, track, seqName);
 printf("Predicted mRNA</A> \n");
 puts("</LI>\n");
@@ -569,46 +570,33 @@
             {
             dyStringAppend(ds, ",\"fields\":{");
             char *fieldsCopy = cloneString(detailsJsFieldsStr);
             char *fieldNames[256];
             int nFields = chopCommas(fieldsCopy, fieldNames);
             boolean first = TRUE;
             int fi;
             for (fi = 0; fi < nFields; fi++)
                 {
                 char *fn = trimSpaces(fieldNames[fi]);
                 char *fv = slPairFindVal(extraFieldPairs, fn);
                 if (fv == NULL)
                     fv = "";
                 if (!first)
                     dyStringAppendC(ds, ',');
-                dyStringPrintf(ds, "\"%s\":", fn);
-                dyStringAppendC(ds, '"');
-                // JSON-escape the value
-                char *c;
-                for (c = fv; *c; c++)
-                    {
-                    if (*c == '"')
-                        dyStringAppend(ds, "\\\"");
-                    else if (*c == '\\')
-                        dyStringAppend(ds, "\\\\");
-                    else if (*c == '\n')
-                        dyStringAppend(ds, "\\n");
-                    else
-                        dyStringAppendC(ds, *c);
-                    }
-                dyStringAppendC(ds, '"');
+                char *escaped = jsonStringEscape(fv);
+                dyStringPrintf(ds, "\"%s\":\"%s\"", fn, escaped);
+                freeMem(escaped);
                 first = FALSE;
                 }
             dyStringAppendC(ds, '}');
             }
 
         // Include detailsJsArgs if present
         char *detailsJsArgs = trackDbSetting(tdb, "detailsJsArgs");
         if (detailsJsArgs)
             dyStringPrintf(ds, ",\"args\":%s", detailsJsArgs);
 
         dyStringAppend(ds, "};\n");
 
         // Call the default function derived from each JS filename (strip .js)
         // e.g. barChart.js -> barChart(bedDetails)
         for (ji = 0; ji < jsFileCount; ji++)