fix: add bounds checks in eval_select_simple for null/empty host_eval_ctx; remove empty_ctx hack

- simple_num/simple_str: guard h->numvals/strvals NULL and idx out-of-range before array access
- eval_select_simple SEL_RESNAME: guard host->numvals NULL and idx bounds before deref
- eval_select_inner SEL_RESNAME (memoizing path): same NULL/bounds guards for numvals and strvals
- build_host_eval_ctx: return valid empty context (num_res=0, NULL arrays) instead of NULL when num_res<=0
- sched_meet_host_selection: remove empty_ctx stack hack; always call build_host_eval_ctx which now handles the zero-resource case cleanly
This commit is contained in:
Rongsong Shen 2026-04-30 05:20:37 +00:00
parent 40261b7e96
commit 8cff4ac889
2 changed files with 27 additions and 27 deletions

View file

@ -527,15 +527,19 @@ static int is_str_cmp(const xce_select_node_t* node)
static double simple_num(const xce_select_node_t* n, const host_eval_ctx_t* h)
{
return n->type == SEL_NUM ? n->u.numval
: h->numvals[n->u.resname.res_idx];
if (n->type == SEL_NUM) return n->u.numval;
int idx = n->u.resname.res_idx;
if (h->numvals == NULL || idx < 0 || idx >= h->num_res) return 0.0;
return h->numvals[idx];
}
static const char* simple_str(const xce_select_node_t* n,
const host_eval_ctx_t* h)
{
return n->type == SEL_STR ? n->u.strval
: h->strvals[n->u.resname.res_idx];
if (n->type == SEL_STR) return n->u.strval;
int idx = n->u.resname.res_idx;
if (h->strvals == NULL || idx < 0 || idx >= h->num_res) return NULL;
return h->strvals[idx];
}
/* Safe cache reads: use cached value when in-bounds, fall back to host data
@ -566,8 +570,11 @@ int eval_select_simple(const xce_select_node_t* root,
case SEL_RESNAME:
switch (root->u.resname.res_type) {
case RES_TYPE_BOOL:
case RES_TYPE_NUMERIC:
return host->numvals[root->u.resname.res_idx] != 0.0 ? 1 : 0;
case RES_TYPE_NUMERIC: {
int idx = root->u.resname.res_idx;
if (host->numvals == NULL || idx < 0 || idx >= host->num_res) return 0;
return host->numvals[idx] != 0.0 ? 1 : 0;
}
case RES_TYPE_STRING:
return -1;
}
@ -670,13 +677,17 @@ static int eval_select_inner(const xce_select_node_t* node,
switch (node->u.resname.res_type) {
case RES_TYPE_BOOL:
case RES_TYPE_NUMERIC: {
double v = host->numvals[node->u.resname.res_idx];
int idx = node->u.resname.res_idx;
double v = (host->numvals != NULL && idx >= 0 && idx < host->num_res)
? host->numvals[idx] : 0.0;
if (node->node_id < ctx->num_vals_cap)
ctx->num_vals[node->node_id] = v;
return v != 0.0 ? 1 : 0;
}
case RES_TYPE_STRING: {
const char* sv = host->strvals[node->u.resname.res_idx];
int idx = node->u.resname.res_idx;
const char* sv = (host->strvals != NULL && idx >= 0 && idx < host->num_res)
? host->strvals[idx] : NULL;
if (node->node_id < ctx->str_vals_cap)
ctx->str_vals[node->node_id] = sv;
return -1;

View file

@ -132,8 +132,9 @@ build_host_eval_ctx(const xce_sched_worker_t* w, int num_res)
if (ctx == NULL) return NULL;
if (num_res <= 0) {
free(ctx);
return NULL;
/* valid empty context — numvals/strvals remain NULL, bounds checks protect access */
ctx->num_res = 0;
return ctx;
}
double* numvals = calloc(num_res, sizeof(double));
@ -185,26 +186,14 @@ int sched_meet_host_selection(xce_scheduler_t* sched, xce_sched_worker_t* w,
int num_res = (int)w->resvals.caps;
/* When num_res == 0, build_host_eval_ctx returns NULL (no resource slots).
* Use an empty stack-allocated context so eval_select_simple can still
* evaluate constant sub-expressions (SEL_TRUE, SEL_FALSE, SEL_ANY). */
host_eval_ctx_t empty_ctx = { .num_res = 0, .numvals = NULL, .strvals = NULL };
host_eval_ctx_t* hctx;
if (num_res <= 0) {
hctx = &empty_ctx;
} else {
hctx = build_host_eval_ctx(w, num_res);
if (hctx == NULL) {
/* OOM: conservatively pass host */
return 1;
}
host_eval_ctx_t* hctx = build_host_eval_ctx(w, num_res);
if (hctx == NULL) {
/* OOM: conservatively pass host */
return 1;
}
int rc = eval_select_simple(s->root, hctx);
if (hctx != &empty_ctx) {
free_host_eval_ctx(hctx);
}
free_host_eval_ctx(hctx);
/* eval_select_simple: 1=match, 0=no-match, <0=error (treat as no-match) */
return (rc > 0) ? 1 : 0;