And rewrote strncpy(), since strncpy_s() also exists. Now to test the build.

This commit is contained in:
Pietro Gagliardi 2019-05-31 10:38:47 -04:00
parent 664cf26cdc
commit 644e188e05
5 changed files with 92 additions and 18 deletions

View File

@ -1,4 +1,5 @@
// 16 may 2019
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ui.h"

View File

@ -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"

View File

@ -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"

View File

@ -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;
}

View File

@ -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);
}