#include #include #include #include #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 }