7181c0af889a0eee451b91ff0b23d67f35e0e772
braney
Tue Aug 18 08:39:08 2026 -0700
cheapcgi, customTrack, hgSession, hgPhyloPlace: track in-memory uploads in a registry
Uploaded file contents are handed to the reading code as a text address and
size. Collect that bookkeeping in cheapcgi, which now records each block it
makes and hands back a name for it, and have the custom track, session and
phyloPlace upload paths look the block up by that name.
Also removes the duplicated address/size parsing those callers each had, and
makes lineFileDecompressMem ignore a too-small buffer.
refs #38108
diff --git src/lib/cheapcgi.c src/lib/cheapcgi.c
index cb73dcd9463..2decd97f4de 100644
--- src/lib/cheapcgi.c
+++ src/lib/cheapcgi.c
@@ -231,30 +231,81 @@
//============ END of javascript inline-separation routines ===============
/* These three variables hold the parsed version of cgi variables. */
static char *inputString = NULL;
static unsigned long inputSize;
static struct hash *inputHash = NULL;
static struct cgiVar *inputList = NULL;
static boolean haveCookiesHash = FALSE;
static struct hash *cookieHash = NULL;
static struct cgiVar *cookieList = NULL;
+/* An uploaded file is passed on to the code that reads it as the address and
+ * size of the bytes in memory, written as text into a cgi variable. Every cgi
+ * variable can also be set by the request, so the address has to be checked
+ * against the blocks we handed out before anything dereferences it. These
+ * blocks are recorded here, keyed by the same text that names them. */
+static struct hash *memBlobHash = NULL;
+
+struct memBlob
+/* A block of memory named by address in a cgi or cart variable. */
+ {
+ char *mem; /* Start of the block. */
+ unsigned long size; /* Size of the block. */
+ };
+
+char *cgiMemBlobRegister(char *mem, unsigned long size)
+/* Record a block of memory that may be named by address in a cgi or cart
+ * variable, and return the "
" text that names it. The
+ * returned string is allocated here and belongs to the caller. */
+{
+char spec[64];
+safef(spec, sizeof(spec), "%lu %lu", (unsigned long)mem, size);
+if (memBlobHash == NULL)
+ memBlobHash = hashNew(4);
+struct memBlob *blob = hashFindVal(memBlobHash, spec);
+if (blob == NULL)
+ {
+ AllocVar(blob);
+ blob->mem = mem;
+ blob->size = size;
+ hashAdd(memBlobHash, spec, blob);
+ }
+return cloneString(spec);
+}
+
+char *cgiMemBlobFind(char *spec, unsigned long *retSize)
+/* Return the block of memory named by spec, which is " " text
+ * made by cgiMemBlobRegister or by an uploaded file part. Return NULL if this
+ * program never registered such a block, in which case the address came from
+ * the request rather than from us and must not be used. If retSize is not
+ * NULL the size of the block is returned in it. */
+{
+struct memBlob *blob = NULL;
+if (memBlobHash != NULL && spec != NULL)
+ blob = hashFindVal(memBlobHash, spec);
+if (blob == NULL)
+ return NULL;
+if (retSize != NULL)
+ *retSize = blob->size;
+return blob->mem;
+}
+
// maximum length of CGI variables to dump to stderr, 0 = switch off
static int logCgiVarMaxLen = 0;
/* Default cap on total size of CGI input we'll accept, excluding
* uploaded files. Used if the GB_CGI_INPUT_SIZE_LIMIT env var
* (typically supplied via Apache SetEnv) is unset or invalid.
* See initCgiInput. */
#define CGI_INPUT_SIZE_LIMIT_DEFAULT (1024*1024)
static long cgiInputSizeLimit()
/* Return the active CGI input size cap. */
{
static long cached = -1;
if (cached < 0)
{
@@ -682,37 +733,33 @@
safef(varNameFilename, sizeof(varNameFilename), "%s__filename", cdName);
AllocVar(el);
if (lastPathSep)
el->val = cloneString(lastPathSep+1);
else
el->val = cloneString(cdFileName);
slAddHead(&list, el);
hashAddSaveName(hash, varNameFilename, el, &el->name);
}
if (mp->data)
{
if (mp->binary)
{
char varNameBinary[256];
- char addrSizeBuf[40];
safef(varNameBinary,sizeof(varNameBinary),"%s__binary",cdName);
- safef(addrSizeBuf,sizeof(addrSizeBuf),"%lu %llu",
- (unsigned long)mp->data,
- (unsigned long long)mp->size);
AllocVar(el);
- el->val = cloneString(addrSizeBuf);
+ el->val = cgiMemBlobRegister(mp->data, (unsigned long)mp->size);
slAddHead(&list, el);
hashAddSaveName(hash, varNameBinary, el, &el->name);
}
else /* normal variable, not too big, does not contain zeros */
{
AllocVar(el);
el->val = mp->data;
slAddHead(&list, el);
hashAddSaveName(hash, cdName, el, &el->name);
}
}
else if (mp->fileName)
{
char varNameData[256];
safef(varNameData, sizeof(varNameData), "%s__data", cdName);