And rewrote strncpy(), since strncpy_s() also exists. Now to test the build.
This commit is contained in:
parent
664cf26cdc
commit
644e188e05
|
@ -1,4 +1,5 @@
|
|||
// 16 may 2019
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "ui.h"
|
||||
|
|
|
@ -3,5 +3,6 @@
|
|||
#include "start.h"
|
||||
|
||||
extern int sharedbitsPrefixName(Vsnprintf)(char *s, size_t n, const char *fmt, va_list ap);
|
||||
extern char *sharedbitsPrefixName(Strncpy)(char *dest, const char *src, size_t n);
|
||||
|
||||
#include "end.h"
|
||||
|
|
|
@ -3,6 +3,13 @@
|
|||
|
||||
#include "start.h"
|
||||
|
||||
#ifdef sharedbitsStatic
|
||||
sharedBitsStatic
|
||||
#else
|
||||
extern
|
||||
#endif
|
||||
void sharedbitsPrefixName(InternalError)(const char *fmt, ...);
|
||||
|
||||
#ifdef sharedbitsStatic
|
||||
sharedbitsStatic
|
||||
#endif
|
||||
|
@ -16,11 +23,31 @@ int sharedbitsPrefixName(Vsnprintf)(char *s, size_t n, const char *fmt, va_list
|
|||
// TODO figure out how to disambiguate between encoding errors (returns negative value; does not have documented errno values), other errors (returns negative value; errno == EINVAL), and truncations (returns -1; does not have documented errno values)
|
||||
ret = vsnprintf_s(s, n, _TRUNCATE, fmt, ap);
|
||||
if (ret == -1)
|
||||
return n;
|
||||
// TODO make this safe
|
||||
return (int) n;
|
||||
return ret;
|
||||
#else
|
||||
return vsnprintf(s, n, fmt, ap);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef sharedbitsStatic
|
||||
sharedbitsStatic
|
||||
#endif
|
||||
char *sharedbitsPrefixName(Strncpy)(char *dest, const char *src, size_t n)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
errno_t err;
|
||||
|
||||
// because strncpy_s() doesn't do this
|
||||
memset(dest, '\0', n * sizeof (char));
|
||||
err = strncpy_s(dest, n, src, _TRUNCATE);
|
||||
if (err != 0 && err != STRUNCATE)
|
||||
sharedbitsStaticName(InternalError)("error calling strncpy_s(): %s (%d)", strerror(err), err);
|
||||
return dest;
|
||||
#else
|
||||
return strncpy(dest, src, n);
|
||||
#endif
|
||||
}
|
||||
|
||||
#include "end.h"
|
||||
|
|
|
@ -56,7 +56,7 @@ char *testingprivStrdup(const char *s)
|
|||
|
||||
n = strlen(s);
|
||||
t = (char *) testingprivAlloc((n + 1) * sizeof (char), "char[]");
|
||||
strncpy(t, s, n + 1);
|
||||
testingprivImplStrncpy(t, s, n + 1);
|
||||
return t;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,38 @@ struct errorCase {
|
|||
};
|
||||
|
||||
static struct errorCase *current = NULL;
|
||||
static bool memoryExhausted = false;
|
||||
static char *caseError = NULL;
|
||||
static char caseErrorMemoryExhausted[] = "memory exhausted";
|
||||
static char caseErrorEncodingError[] = "encoding error while handling other case error";
|
||||
|
||||
#define sharedbitsPrefix priv
|
||||
#define sharedbitsStatic static
|
||||
#include "../../sharedbits/strsafe_impl.h"
|
||||
#undef sharedbitsStatic
|
||||
#undef sharedbitsPrefix
|
||||
|
||||
static void privInternalError(const char *fmt, ...)
|
||||
{
|
||||
va_list ap, ap2;
|
||||
|
||||
va_start(ap, fmt);
|
||||
va_copy(ap2, ap);
|
||||
n = privVsnprintf(NULL, 0, fmt, ap2);
|
||||
va_end(ap2);
|
||||
if (n < 0) {
|
||||
caseError = caseErrorEncodingError;
|
||||
va_end(ap);
|
||||
return;
|
||||
}
|
||||
caseError = (char *) malloc((n + 1) * sizeof (char));
|
||||
if (caseError == NULL) {
|
||||
caseError = caseErrorMemoryExhausted;
|
||||
va_end(ap);
|
||||
return;
|
||||
}
|
||||
privVsnprintf(otherError, n + 1, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void catalogProgrammerError(const char *prefix, const char *msg, const char *suffix, bool internal)
|
||||
{
|
||||
|
@ -26,20 +57,24 @@ static void catalogProgrammerError(const char *prefix, const char *msg, const ch
|
|||
n = strlen(prefix);
|
||||
current->prefixGot = (char *) malloc((n + 1) * sizeof (char));
|
||||
if (current->prefixGot == NULL) {
|
||||
memoryExhausted = true;
|
||||
caseError = caseErrorMemoryExhausted;
|
||||
return;
|
||||
}
|
||||
strncpy(current->prefixGot, prefix, n + 1);
|
||||
privStrncpy(current->prefixGot, prefix, n + 1);
|
||||
if (caseError != NULL)
|
||||
return;
|
||||
}
|
||||
current->internalGot = internal;
|
||||
if (strstr(msg, current->msgWant) == NULL) {
|
||||
n = strlen(msg);
|
||||
current->msgGot = (char *) malloc((n + 1) * sizeof (char));
|
||||
if (current->msgGot == NULL) {
|
||||
memoryExhausted = true;
|
||||
caseError = caseErrorMemoryExhausted;
|
||||
return;
|
||||
}
|
||||
strncpy(current->msgGot, msg, n + 1);
|
||||
privStrncpy(current->msgGot, msg, n + 1);
|
||||
if (caseError != NULL)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,7 +84,7 @@ static struct errorCase *newCase(void)
|
|||
|
||||
p = (struct errorCase *) malloc(sizeof (struct errorCase));
|
||||
if (p == NULL) {
|
||||
memoryExhausted = true;
|
||||
caseError = caseErrorMemoryExhausted;
|
||||
return NULL;
|
||||
}
|
||||
memset(p, 0, sizeof (struct errorCase));
|
||||
|
@ -94,7 +129,7 @@ static void reportCases(testingT *t, struct errorCase *p)
|
|||
|
||||
#define allcallsCase(f, ...) { \
|
||||
current = newCase(); \
|
||||
if (memoryExhausted) \
|
||||
if (caseError != NULL) \
|
||||
return first; \
|
||||
current->name = #f "()"; \
|
||||
current->msgWant = "attempt to call " #f "() " allcallsMsgSuffix; \
|
||||
|
@ -104,7 +139,7 @@ static void reportCases(testingT *t, struct errorCase *p)
|
|||
if (last != NULL) \
|
||||
last->next = current; \
|
||||
last = current; \
|
||||
if (memoryExhausted) \
|
||||
if (caseError != NULL) \
|
||||
return first; \
|
||||
}
|
||||
|
||||
|
@ -124,13 +159,17 @@ testingTestInSet(beforeTests, FunctionsFailBeforeInit)
|
|||
{
|
||||
struct errorCase *cases;
|
||||
|
||||
memoryExhausted = false;
|
||||
caseError = NULL;
|
||||
uiprivTestHookReportProgrammerError(catalogProgrammerError);
|
||||
cases = runCasesBeforeInit();
|
||||
uiprivTestHookReportProgrammerError(NULL);
|
||||
if (memoryExhausted) {
|
||||
if (caseError != NULL) {
|
||||
freeCases(cases);
|
||||
testingTFatalf(t, "memory exhausted running tests");
|
||||
testingTErrorf(t, "%s running tests", caseError);
|
||||
if (caseError != caseErrorMemoryExhausted && caseError != caseErrorEncodingError)
|
||||
free(caseError);
|
||||
caseError = NULL;
|
||||
testingTFailNow();
|
||||
}
|
||||
reportCases(t, cases);
|
||||
freeCases(cases);
|
||||
|
@ -154,8 +193,8 @@ static void wrongThreadThreadProc(void *data)
|
|||
uiprivTestHookReportProgrammerError(catalogProgrammerError);
|
||||
*pCases = runCasesWrongThread();
|
||||
uiprivTestHookReportProgrammerError(NULL);
|
||||
// do this now in case something gets allocated before we return to the main thread
|
||||
if (memoryExhausted) {
|
||||
// do this now in case memory was exhausted and something gets allocated before we return to the main thread
|
||||
if (caseError != NULL) {
|
||||
freeCases(*pCases);
|
||||
*pCases = NULL;
|
||||
}
|
||||
|
@ -167,15 +206,21 @@ testingTest(FunctionsFailOnWrongThread)
|
|||
threadThread *thread;
|
||||
threadSysError err;
|
||||
|
||||
memoryExhausted = false;
|
||||
caseError = NULL;
|
||||
err = threadNewThread(wrongThreadThreadProc, &cases, &thread);
|
||||
if (err != 0)
|
||||
testingTFatalf(t, "error creating thread: " threadSysErrorFmt, threadSysErrorFmtArg(err));
|
||||
err = threadThreadWaitAndFree(thread);
|
||||
if (err != 0)
|
||||
testingTFatalf(t, "error waiting for thread to finish: " threadSysErrorFmt, threadSysErrorFmtArg(err));
|
||||
if (memoryExhausted)
|
||||
testingTFatalf(t, "memory exhausted running tests");
|
||||
if (caseError != NULL) {
|
||||
freeCases(cases);
|
||||
testingTErrorf(t, "%s running tests", caseError);
|
||||
if (caseError != caseErrorMemoryExhausted && caseError != caseErrorEncodingError)
|
||||
free(caseError);
|
||||
caseError = NULL;
|
||||
testingTFailNow();
|
||||
}
|
||||
reportCases(t, cases);
|
||||
freeCases(cases);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue