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);