Fix File stat-before-open crash risk, JSON string-quoting bug, and MString buffer overflow

- File: stat() only after a successful open() (previously ran first with
  its result ignored, feeding a missing file's garbage st_size into a
  realloc - could crash the whole APIServer on a request for a
  nonexistent static asset)
- JString::setString(): always quote+escape the value instead of going
  through set()'s literal-value guess, which misclassified any string
  starting with digits (e.g. a UUID) as a bare numeric literal and wrote
  it unquoted, corrupting later edits to the same JSON document
- MString::remove() (both overloads): fixed an off-by-one that read one
  byte past the buffer on a completely full string (found via ASan under
  concurrent load)
- CGIFormData: added fields() so callers can iterate every parsed field
  without knowing names in advance (used to merge POST body into
  jet::Global::variables the same way query-string params already are)
This commit is contained in:
Brad Arant committed 2026-09-03 05:14:24 +00:00
1 parent d7057ebb00
commit 78c45d378c
6 files changed
+79 -8

No files matched your search

+20 -5
View File
@@ -17,19 +17,34 @@ namespace coreutils {
this->fileName = fileName;
struct stat status;
stat(fileName.c_str(), &status);
buffer = NULL;
setBufferSize(status.st_size);
fd = ::open(fileName.c_str(), mode, authority);
if(fd < 0) {
std::stringstream temp;
temp << "Error opening file " << fileName << ".";
throw Exception(temp.str(), __FILE__, __LINE__);
}
// stat() only after a successful open(), and only used to size the
// read buffer - previously this ran BEFORE the open()/fd check with
// its return value ignored, so a missing file left the stat struct fully
// uninitialized and fed that garbage st_size straight into
// setBufferSize()'s realloc(), before the open-failure path ever
// got a chance to throw its clean Exception. Found while adding a
// static-asset route (GET /assets/{filename}) that legitimately
// hits this path on every request for a nonexistent file - a
// garbage-sized realloc there could abort/crash the whole
// long-running APIServer process (shared with every other live
// route) instead of cleanly 500ing just that one request.
struct stat status;
if (fstat(fd, &status) != 0) {
std::stringstream temp;
temp << "Error statting file " << fileName << ".";
throw Exception(temp.str(), __FILE__, __LINE__);
}
setBufferSize(status.st_size);
}
File::~File() {