feat(job-array-one-based-index): classify every job submission first (task 2.1)
handle_jobsubmit classifies (first_jobid, array_size) before the field checks, the before-event hook and any registry access: a tagged array starting at index 0 is answered with the new E_XCE_ARRAY_START0 and an ERROR log asking for the client to be upgraded (7.1, wins per 7.9); size 0, tags 2/3, untagged multi-element submissions and arrays whose last element exceeds 32767 (checked without addition) get -EINVAL. Nothing is stored for a rejected submission. This also closes a crash: a size-0 submission used to reach payload building and overflow calloc. Existing array 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:
parent
ef728435d4
commit
e6c484a0e7
11 changed files with 574 additions and 19 deletions
|
|
@ -2431,6 +2431,31 @@ static int handle_jobsubmit_array(cluster_t* c, endpoint_t* ep,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* job-array-one-based-index (Req 7.1-7.5, 7.9; design "ControllerValidate"):
|
||||
* classify a submission from its first ID and its wire element count only.
|
||||
* 7.1 is checked first, so an index-0 array is answered as such whatever
|
||||
* else is wrong with it (7.9); then 7.4, 7.5, 7.3 and 7.2, all INVALID.
|
||||
* 7.2 is evaluated as size > 32768 - idx (idx >= 1 here), never as
|
||||
* idx + size - 1 > 32767, so no 64-bit size can wrap past it. */
|
||||
jobsubmit_class_t jobsubmit_classify(uint64_t first_jobid, uint64_t size)
|
||||
{
|
||||
uint64_t tag = EXTRACT_ID_TAG(first_jobid);
|
||||
int is_array = is_array_tag(first_jobid);
|
||||
uint64_t idx = array_idx(first_jobid);
|
||||
|
||||
if (is_array && idx == 0) /* 7.1 */
|
||||
return JOBSUBMIT_INDEX0;
|
||||
if (size == 0) /* 7.4 */
|
||||
return JOBSUBMIT_INVALID;
|
||||
if (tag != 0 && !is_array) /* 7.5 */
|
||||
return JOBSUBMIT_INVALID;
|
||||
if (!is_array && size > 1) /* 7.3 */
|
||||
return JOBSUBMIT_INVALID;
|
||||
if (is_array && size > (MAX_ARRAY_IDX + 1) - idx) /* 7.2 */
|
||||
return JOBSUBMIT_INVALID;
|
||||
return JOBSUBMIT_OK;
|
||||
}
|
||||
|
||||
int handle_jobsubmit(cluster_t* c, endpoint_t* ep, xce_request_t* request)
|
||||
{
|
||||
uint64_t jobid;
|
||||
|
|
@ -2444,6 +2469,38 @@ int handle_jobsubmit(cluster_t* c, endpoint_t* ep, xce_request_t* request)
|
|||
|
||||
init_reply_by_req(&reply, request);
|
||||
|
||||
/* job-array-one-based-index (Req 7.1-7.6, 7.9): classify before the
|
||||
* field checks, the BEFORE_EVENT hook and any registry/table access, so
|
||||
* a rejected submission is answered with its class's status alone and
|
||||
* nothing is stored. */
|
||||
switch (jobsubmit_classify(submit->jobid, submit->array_size)) {
|
||||
case JOBSUBMIT_INDEX0: {
|
||||
char idstr[64];
|
||||
|
||||
fmt_jobid(idstr, sizeof(idstr), submit->jobid);
|
||||
ERROR("jobsubmit: rejected array submission %s (%lu elements) from "
|
||||
"%s: array element numbers start at 1, this submission starts "
|
||||
"at 0; the submitting client must be upgraded",
|
||||
idstr, (unsigned long)submit->array_size,
|
||||
(request->from != NULL && request->from->name != NULL)
|
||||
? request->from->name
|
||||
: "unknown");
|
||||
reply.status = -E_XCE_ARRAY_START0;
|
||||
reply.data_which = RequestReply_data_nodata;
|
||||
|
||||
xce_reply(ep, c->myhost, &reply);
|
||||
return -E_XCE_ARRAY_START0;
|
||||
}
|
||||
case JOBSUBMIT_INVALID:
|
||||
reply.status = -EINVAL;
|
||||
reply.data_which = RequestReply_data_nodata;
|
||||
|
||||
xce_reply(ep, c->myhost, &reply);
|
||||
return -EINVAL;
|
||||
case JOBSUBMIT_OK:
|
||||
break;
|
||||
}
|
||||
|
||||
if (NULLSTR(submit->submit->user) || NULLSTR(submit->submit->queue)
|
||||
|| (submit->submit->start_info == NULL)
|
||||
|| NULLSTR(submit->submit->start_info->cmdline)) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue