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
|
// 16 may 2019
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
|
|
|
@ -3,5 +3,6 @@
|
||||||
#include "start.h"
|
#include "start.h"
|
||||||
|
|
||||||
extern int sharedbitsPrefixName(Vsnprintf)(char *s, size_t n, const char *fmt, va_list ap);
|
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"
|
#include "end.h"
|
||||||
|
|
|
@ -3,6 +3,13 @@
|
||||||
|
|
||||||
#include "start.h"
|
#include "start.h"
|
||||||
|
|
||||||
|
#ifdef sharedbitsStatic
|
||||||
|
sharedBitsStatic
|
||||||
|
#else
|
||||||
|
extern
|
||||||
|
#endif
|
||||||
|
void sharedbitsPrefixName(InternalError)(const char *fmt, ...);
|
||||||
|
|
||||||
#ifdef sharedbitsStatic
|
#ifdef sharedbitsStatic
|
||||||
sharedbitsStatic
|
sharedbitsStatic
|
||||||
#endif
|
#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)
|
// 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);
|
ret = vsnprintf_s(s, n, _TRUNCATE, fmt, ap);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
return n;
|
// TODO make this safe
|
||||||
|
return (int) n;
|
||||||
return ret;
|
return ret;
|
||||||
#else
|
#else
|
||||||
return vsnprintf(s, n, fmt, ap);
|
return vsnprintf(s, n, fmt, ap);
|
||||||
#endif
|
#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"
|
#include "end.h"
|
||||||
|
|
|
@ -56,7 +56,7 @@ char *testingprivStrdup(const char *s)
|
||||||
|
|
||||||
n = strlen(s);
|
n = strlen(s);
|
||||||
t = (char *) testingprivAlloc((n + 1) * sizeof (char), "char[]");
|
t = (char *) testingprivAlloc((n + 1) * sizeof (char), "char[]");
|
||||||
strncpy(t, s, n + 1);
|
testingprivImplStrncpy(t, s, n + 1);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,38 @@ struct errorCase {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct errorCase *current = NULL;
|
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)
|
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);
|
n = strlen(prefix);
|
||||||
current->prefixGot = (char *) malloc((n + 1) * sizeof (char));
|
current->prefixGot = (char *) malloc((n + 1) * sizeof (char));
|
||||||
if (current->prefixGot == NULL) {
|
if (current->prefixGot == NULL) {
|
||||||
memoryExhausted = true;
|
caseError = caseErrorMemoryExhausted;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
strncpy(current->prefixGot, prefix, n + 1);
|
privStrncpy(current->prefixGot, prefix, n + 1);
|
||||||
|
if (caseError != NULL)
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
current->internalGot = internal;
|
current->internalGot = internal;
|
||||||
if (strstr(msg, current->msgWant) == NULL) {
|
if (strstr(msg, current->msgWant) == NULL) {
|
||||||
n = strlen(msg);
|
n = strlen(msg);
|
||||||
current->msgGot = (char *) malloc((n + 1) * sizeof (char));
|
current->msgGot = (char *) malloc((n + 1) * sizeof (char));
|
||||||
if (current->msgGot == NULL) {
|
if (current->msgGot == NULL) {
|
||||||
memoryExhausted = true;
|
caseError = caseErrorMemoryExhausted;
|
||||||
return;
|
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));
|
p = (struct errorCase *) malloc(sizeof (struct errorCase));
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
memoryExhausted = true;
|
caseError = caseErrorMemoryExhausted;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
memset(p, 0, sizeof (struct errorCase));
|
memset(p, 0, sizeof (struct errorCase));
|
||||||
|
@ -94,7 +129,7 @@ static void reportCases(testingT *t, struct errorCase *p)
|
||||||
|
|
||||||
#define allcallsCase(f, ...) { \
|
#define allcallsCase(f, ...) { \
|
||||||
current = newCase(); \
|
current = newCase(); \
|
||||||
if (memoryExhausted) \
|
if (caseError != NULL) \
|
||||||
return first; \
|
return first; \
|
||||||
current->name = #f "()"; \
|
current->name = #f "()"; \
|
||||||
current->msgWant = "attempt to call " #f "() " allcallsMsgSuffix; \
|
current->msgWant = "attempt to call " #f "() " allcallsMsgSuffix; \
|
||||||
|
@ -104,7 +139,7 @@ static void reportCases(testingT *t, struct errorCase *p)
|
||||||
if (last != NULL) \
|
if (last != NULL) \
|
||||||
last->next = current; \
|
last->next = current; \
|
||||||
last = current; \
|
last = current; \
|
||||||
if (memoryExhausted) \
|
if (caseError != NULL) \
|
||||||
return first; \
|
return first; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,13 +159,17 @@ testingTestInSet(beforeTests, FunctionsFailBeforeInit)
|
||||||
{
|
{
|
||||||
struct errorCase *cases;
|
struct errorCase *cases;
|
||||||
|
|
||||||
memoryExhausted = false;
|
caseError = NULL;
|
||||||
uiprivTestHookReportProgrammerError(catalogProgrammerError);
|
uiprivTestHookReportProgrammerError(catalogProgrammerError);
|
||||||
cases = runCasesBeforeInit();
|
cases = runCasesBeforeInit();
|
||||||
uiprivTestHookReportProgrammerError(NULL);
|
uiprivTestHookReportProgrammerError(NULL);
|
||||||
if (memoryExhausted) {
|
if (caseError != NULL) {
|
||||||
freeCases(cases);
|
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);
|
reportCases(t, cases);
|
||||||
freeCases(cases);
|
freeCases(cases);
|
||||||
|
@ -154,8 +193,8 @@ static void wrongThreadThreadProc(void *data)
|
||||||
uiprivTestHookReportProgrammerError(catalogProgrammerError);
|
uiprivTestHookReportProgrammerError(catalogProgrammerError);
|
||||||
*pCases = runCasesWrongThread();
|
*pCases = runCasesWrongThread();
|
||||||
uiprivTestHookReportProgrammerError(NULL);
|
uiprivTestHookReportProgrammerError(NULL);
|
||||||
// do this now in case something gets allocated before we return to the main thread
|
// do this now in case memory was exhausted and something gets allocated before we return to the main thread
|
||||||
if (memoryExhausted) {
|
if (caseError != NULL) {
|
||||||
freeCases(*pCases);
|
freeCases(*pCases);
|
||||||
*pCases = NULL;
|
*pCases = NULL;
|
||||||
}
|
}
|
||||||
|
@ -167,15 +206,21 @@ testingTest(FunctionsFailOnWrongThread)
|
||||||
threadThread *thread;
|
threadThread *thread;
|
||||||
threadSysError err;
|
threadSysError err;
|
||||||
|
|
||||||
memoryExhausted = false;
|
caseError = NULL;
|
||||||
err = threadNewThread(wrongThreadThreadProc, &cases, &thread);
|
err = threadNewThread(wrongThreadThreadProc, &cases, &thread);
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
testingTFatalf(t, "error creating thread: " threadSysErrorFmt, threadSysErrorFmtArg(err));
|
testingTFatalf(t, "error creating thread: " threadSysErrorFmt, threadSysErrorFmtArg(err));
|
||||||
err = threadThreadWaitAndFree(thread);
|
err = threadThreadWaitAndFree(thread);
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
testingTFatalf(t, "error waiting for thread to finish: " threadSysErrorFmt, threadSysErrorFmtArg(err));
|
testingTFatalf(t, "error waiting for thread to finish: " threadSysErrorFmt, threadSysErrorFmtArg(err));
|
||||||
if (memoryExhausted)
|
if (caseError != NULL) {
|
||||||
testingTFatalf(t, "memory exhausted running tests");
|
freeCases(cases);
|
||||||
|
testingTErrorf(t, "%s running tests", caseError);
|
||||||
|
if (caseError != caseErrorMemoryExhausted && caseError != caseErrorEncodingError)
|
||||||
|
free(caseError);
|
||||||
|
caseError = NULL;
|
||||||
|
testingTFailNow();
|
||||||
|
}
|
||||||
reportCases(t, cases);
|
reportCases(t, cases);
|
||||||
freeCases(cases);
|
freeCases(cases);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue