fix(lib,scheduler): allocation constructors and allocators report OOM instead of building NULL-name records (bug-1882)
make_alloc() and make_host_alloc() assigned strdup() results unchecked, so under memory exhaustion they returned a record whose resname/reserve/ host was NULL; merge_job_alloc()'s same_alloc_slot() (bug-1863) then strcmp()'d it (ASAN SEGV at xcealloc.c:337). make_alloc() also passed a NULL resname straight to strdup(). - xcealloc.c: make_alloc()/make_host_alloc() reject a NULL name (EINVAL) and check every strdup(), freeing what they built and returning NULL (ENOMEM); on failure make_host_alloc()'s caller keeps `allocs`. dup_host_alloc() frees its partial copy on failure instead of leaking. - scheduler.c sched_make_allocs(): a record that cannot be built fails the whole array (NULL, ENOMEM) instead of leaving a NULL entry. - seqjob/parjob my_alloc(): check every constructor; on failure free what was built (parjob also rolls back the remaining claims) and return -ENOMEM with ctx->alloc NULL -- the caller moves ctx.alloc onto the job whatever the rc. Tests: new xcealloc_oom_test (8, --wrap=strdup) and sched_make_allocs_oom_test (real scheduler_srcs + --wrap=strdup); a new -ENOMEM test in the seqjob and parjob allocator suites. All RED before (SEGV / "Expected NULL" / "Expected -12 Was 1"), GREEN after. xce-build.sh all asan: 115/115 suites OK, Go tests OK. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c02d8e5cf6
commit
f9146864a3
10 changed files with 563 additions and 12 deletions
|
|
@ -8,21 +8,34 @@
|
|||
#include "xce/types.h"
|
||||
#include "xcealloc.h"
|
||||
|
||||
/* make_alloc() never returns a record with a NULL resname or reserve
|
||||
* (bug-1882): a NULL resname is rejected (errno EINVAL) and a failed
|
||||
* strdup() frees what was built and returns NULL (errno ENOMEM), because
|
||||
* merge_job_alloc()'s slot matching and every other consumer strcmp() these
|
||||
* strings. */
|
||||
xce_alloc_t* make_alloc(char* resname, char* reserve, uint64_t instid,
|
||||
float value, int duration)
|
||||
{
|
||||
xce_alloc_t* alloc = NULL;
|
||||
|
||||
if (resname == NULL) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
alloc = (xce_alloc_t*)calloc(1, sizeof(*alloc));
|
||||
if (alloc == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
alloc->resname = strdup(resname);
|
||||
if (reserve != NULL) {
|
||||
alloc->reserve = strdup(reserve);
|
||||
} else {
|
||||
alloc->reserve = strdup("");
|
||||
alloc->reserve = strdup((reserve != NULL) ? reserve : "");
|
||||
if ((alloc->resname == NULL) || (alloc->reserve == NULL)) {
|
||||
FREEUP(alloc->resname);
|
||||
FREEUP(alloc->reserve);
|
||||
FREEUP(alloc);
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
alloc->instid = instid;
|
||||
|
|
@ -78,18 +91,32 @@ xce_alloc_t** make_allocs(int nallocs, ...)
|
|||
return allocs;
|
||||
}
|
||||
|
||||
/* make_host_alloc() takes ownership of `allocs` only on success; on failure
|
||||
* (NULL host: EINVAL, failed strdup(): ENOMEM) it returns NULL and the
|
||||
* caller still owns `allocs` (bug-1882: never a record with a NULL host). */
|
||||
xce_host_alloc_t* make_host_alloc(char* host, int nalloc, xce_alloc_t** allocs)
|
||||
{
|
||||
xce_host_alloc_t* halloc = NULL;
|
||||
|
||||
if (host == NULL) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
halloc = (xce_host_alloc_t*)calloc(1, sizeof(*halloc));
|
||||
if (halloc == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
halloc->host = strdup(host);
|
||||
if (halloc->host == NULL) {
|
||||
FREEUP(halloc);
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
halloc->nallocs = nalloc;
|
||||
halloc->allocs = allocs;
|
||||
halloc->host = strdup(host);
|
||||
|
||||
return halloc;
|
||||
}
|
||||
|
|
@ -219,12 +246,16 @@ static xce_host_alloc_t* dup_host_alloc(const xce_host_alloc_t* src)
|
|||
for (i = 0; i < src->nallocs; i++) {
|
||||
allocs[i] = dup_alloc(src->allocs[i]);
|
||||
if (allocs[i] == NULL) {
|
||||
free_ResAlloc_list(src->nallocs, allocs);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
halloc = make_host_alloc(src->host, src->nallocs, allocs);
|
||||
if (halloc == NULL) {
|
||||
free_ResAlloc_list(src->nallocs, allocs);
|
||||
}
|
||||
|
||||
return halloc;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue