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>
105 lines
3.4 KiB
C
105 lines
3.4 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unity/unity.h>
|
|
|
|
#include "utils.h"
|
|
#include "xce/errnox.h"
|
|
|
|
static void test_error_setget(void)
|
|
{
|
|
int myerrno = 1;
|
|
ectx_t* e;
|
|
|
|
SET_ERROR(myerrno);
|
|
e = get_ectx();
|
|
|
|
TEST_ASSERT_TRUE(e != NULL);
|
|
TEST_ASSERT_TRUE(errno == myerrno);
|
|
TEST_ASSERT_TRUE(e->file != NULL);
|
|
TEST_ASSERT_TRUE(e->func != NULL);
|
|
TEST_ASSERT_TRUE(strcmp(e->file, __FILE__) == 0);
|
|
TEST_ASSERT_TRUE(strcmp(e->func, __func__) == 0);
|
|
}
|
|
|
|
#if 0
|
|
static void test_strerror_r(void) {
|
|
char errmsg1[256];
|
|
char errmsg2[256];
|
|
int errors[] ={ENOENT, EINVAL, E_XCE_BAD_JOB, E_XCE_BAD_WORKER, 0};
|
|
int i;
|
|
|
|
for(i = 0; errors[i] != 0; i ++) {
|
|
strerror_r(errors[i], errmsg1, sizeof(errmsg1));
|
|
xce_strerror_r(errors[i], errmsg2, sizeof(errmsg2));
|
|
TEST_ASSERT_TRUE(strcmp(errmsg1, errmsg2) == 0);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* Every XCE error code in [XCE_ERRNO_BASE, E_XCE_MAX) must map to a real string
|
|
* via xce_strerror_r — no NULL deref, no out-of-bounds read of xce_err_str[].
|
|
* Regression for the global-buffer-overflow at utils.c:335: the HA codes
|
|
* E_XCE_NOMASTER/REDIRECT/NOT_READY/STANDBY (10011-10014) were added to the
|
|
* enum but not to xce_err_str[], so formatting them (e.g. ctrlstatus on a
|
|
* failover-exhausted cluster returning E_XCE_NOT_READY) ran off the array.
|
|
* Under ASAN this crashes pre-fix. */
|
|
static void test_strerror_all_xce_codes(void)
|
|
{
|
|
char buf[128];
|
|
int code;
|
|
|
|
for (code = XCE_ERRNO_BASE; code < E_XCE_MAX; code++) {
|
|
buf[0] = '\0';
|
|
int rc = xce_strerror_r(code, buf, sizeof(buf));
|
|
TEST_ASSERT_EQUAL_INT(0, rc); /* every in-range code resolves */
|
|
TEST_ASSERT_TRUE(buf[0] != '\0'); /* to a non-empty string */
|
|
TEST_ASSERT_TRUE(strcmp(buf, "unknown error") != 0); /* a SPECIFIC one */
|
|
}
|
|
|
|
/* the specific HA codes that triggered the crash */
|
|
xce_strerror_r(E_XCE_NOT_READY, buf, sizeof(buf));
|
|
TEST_ASSERT_TRUE(buf[0] != '\0' && strcmp(buf, "unknown error") != 0);
|
|
xce_strerror_r(E_XCE_NOMASTER, buf, sizeof(buf));
|
|
TEST_ASSERT_TRUE(buf[0] != '\0' && strcmp(buf, "unknown error") != 0);
|
|
}
|
|
|
|
/* Out-of-range XCE codes (>= E_XCE_MAX) must fall back to "unknown error",
|
|
* never index past xce_err_str[] (defense in depth against future enum drift). */
|
|
static void test_strerror_out_of_range(void)
|
|
{
|
|
char buf[128];
|
|
|
|
TEST_ASSERT_EQUAL_INT(-1, xce_strerror_r(E_XCE_MAX, buf, sizeof(buf)));
|
|
TEST_ASSERT_TRUE(strcmp(buf, "unknown error") == 0);
|
|
|
|
TEST_ASSERT_EQUAL_INT(-1, xce_strerror_r(E_XCE_MAX + 50, buf, sizeof(buf)));
|
|
TEST_ASSERT_TRUE(strcmp(buf, "unknown error") == 0);
|
|
}
|
|
|
|
/* job-array-one-based-index (Req 7.1): the distinct array-numbering status
|
|
* sits right after E_XCE_STANDBY and its text says numbering starts at 1
|
|
* and the client must be upgraded. */
|
|
static void test_strerror_array_start0(void)
|
|
{
|
|
char buf[128];
|
|
|
|
TEST_ASSERT_EQUAL_INT(E_XCE_STANDBY + 1, E_XCE_ARRAY_START0);
|
|
TEST_ASSERT_EQUAL_INT(0,
|
|
xce_strerror_r(E_XCE_ARRAY_START0, buf, sizeof(buf)));
|
|
TEST_ASSERT_NOT_NULL(strstr(buf, "start at 1"));
|
|
TEST_ASSERT_NOT_NULL(strstr(buf, "upgrade"));
|
|
}
|
|
|
|
void test_error(void)
|
|
{
|
|
printf("\n>> error test\n\n");
|
|
|
|
RUN_TEST(test_error_setget);
|
|
RUN_TEST(test_strerror_all_xce_codes);
|
|
RUN_TEST(test_strerror_out_of_range);
|
|
RUN_TEST(test_strerror_array_start0);
|
|
#if 0
|
|
RUN_TEST(test_strerror_r);
|
|
#endif
|
|
}
|