feat(job-array-one-based-index): guard scheduler array expansion (task 3.1)

The scheduler expands an array push only when the first ID carries the
array marking and the size fits in its block (size <= 32768 - idx, no
addition); otherwise it logs an ERROR naming the array identity and
expands nothing. Pre-upgrade arrays starting at index 0 still expand.
The INFO log names the array identity (array_jobid=...). This also
closes a crash: a malformed push with a huge size overflowed calloc.
Expansion tests move to tagged block|1 first IDs.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Rongsong Shen 2026-10-01 10:24:42 +00:00
parent fe5ddc9854
commit 4f44a68973
Signed by untrusted user: rshen
GPG key ID: 80533536B0EB651C
5 changed files with 147 additions and 31 deletions

View file

@ -37,6 +37,12 @@
* elsewhere is sched_init_config, stubbed below (same as test_handlers.c). */
#include "../src/handler.c"
/* job-array-one-based-index (Req 5.9): array first IDs are tagged
* TAG_JOB_ARRAY, block-aligned, numbered from 1. */
#define ARR_FIRST(blk) \
MAKE_JOBID(1, 2, 1000, TAG_JOB_ARRAY, \
(((uint64_t)(blk)) << N_ARRAY_IDX_BITS) | 1)
int sched_init_config(xce_scheduler_t* s, xce_conf4sched_t* c)
{
(void)s;
@ -179,7 +185,7 @@ static void test_job_array_push_enqueues_raw_descriptor_unexpanded(void)
xce_job_submit_t* popped;
fixture_init(&sched);
ja = init_job_array(5000, 3);
ja = init_job_array(ARR_FIRST(1), 3);
memset(&dataset, 0, sizeof(dataset));
dataset.table = XceData_data_jobArray;
@ -193,7 +199,7 @@ static void test_job_array_push_enqueues_raw_descriptor_unexpanded(void)
popped = pop_job_array_update(&sched);
TEST_ASSERT_EQUAL_PTR(ja, popped); /* same descriptor, not a clone */
TEST_ASSERT_EQUAL_UINT64(5000, popped->jobid);
TEST_ASSERT_EQUAL_UINT64(ARR_FIRST(1), popped->jobid);
TEST_ASSERT_EQUAL_UINT64(3, popped->array_size);
TEST_ASSERT_EQUAL_STRING("normal", popped->submit->queue);
@ -210,7 +216,7 @@ static void test_job_array_null_submit_returns_einval(void)
fixture_init(&sched);
memset(&ja, 0, sizeof(ja));
ja.jobid = 1;
ja.jobid = ARR_FIRST(2);
ja.array_size = 3;
ja.submit = NULL;
@ -280,7 +286,7 @@ static void test_wire_dispatch_chain_delivers_job_array_descriptor(void)
submit.resreq = "type == local";
memset(&job_array, 0, sizeof(job_array));
job_array.jobid = 8000;
job_array.jobid = ARR_FIRST(3);
job_array.array_size = 4;
job_array.submit = &submit;
@ -316,7 +322,7 @@ static void test_wire_dispatch_chain_delivers_job_array_descriptor(void)
* correctly addressed via base_jobid + array_size. */
popped = pop_job_array_update(&sched);
TEST_ASSERT_NOT_NULL(popped);
TEST_ASSERT_EQUAL_UINT64(8000, popped->jobid);
TEST_ASSERT_EQUAL_UINT64(ARR_FIRST(3), popped->jobid);
TEST_ASSERT_EQUAL_UINT64(4, popped->array_size);
TEST_ASSERT_EQUAL_STRING("normal", popped->submit->queue);
free_JobSubmit_ptr(&popped);