Skip to content
Permalink
Browse files

Various Buffer improvements.

Add bufDup() and bufNewUsedC().

Arrange bufNewC() params to match bufNewUsedC() since they have always seemed backward.

Fix bufHex() to only render the used portion of the buffer and fix some places where used was not being set correctly.

Use a union to make macro assignments for all legal values without casting.  This is much more likely to catch bad assignments.
  • Loading branch information...
dwsteele committed May 2, 2019
1 parent 59234f2 commit 498017bcf02560e101703e89b1119d0b48944835
@@ -55,6 +55,10 @@
<p>Don't append <code>strerror()</code> to error message when <code>errno</code> is 0.</p>
</release-item>

<release-item>
<p>Various <code>Buffer</code> improvements.</p>
</release-item>

<release-item>
<p>Add <code>ioWriteStr()</code> and <code>ioWriteStrLine()</code>.</p>
</release-item>
@@ -163,6 +163,7 @@ cryptoHash(CryptoHash *this)
MEM_CONTEXT_BEGIN(this->memContext)
{
this->hash = bufNew((size_t)EVP_MD_size(this->hashType));
bufUsedSet(this->hash, bufSize(this->hash));

cryptoError(!EVP_DigestFinal_ex(this->hashContext, bufPtr(this->hash), NULL), "unable to finalize message hash");

@@ -257,7 +258,7 @@ cryptoHashOneC(const String *type, const unsigned char *message, size_t messageS
cryptoHashProcessC(hash, message, messageSize);

memContextSwitch(MEM_CONTEXT_OLD());
result = bufNewC(bufSize(cryptoHash(hash)), bufPtr(cryptoHash(hash)));
result = bufDup(cryptoHash(hash));
memContextSwitch(MEM_CONTEXT_TEMP());
}
MEM_CONTEXT_TEMP_END();
@@ -320,9 +321,10 @@ cryptoHmacOne(const String *type, const Buffer *key, const Buffer *message)

// Allocate a buffer to hold the hmac
Buffer *result = bufNew((size_t)EVP_MD_size(hashType));
bufUsedSet(result, bufSize(result));

// Calculate the HMAC
HMAC(hashType, bufPtr(key), (int)bufSize(key), bufPtr(message), bufSize(message), bufPtr(result), NULL);
HMAC(hashType, bufPtr(key), (int)bufUsed(key), bufPtr(message), bufUsed(message), bufPtr(result), NULL);

FUNCTION_TEST_RETURN(result);
}
@@ -24,6 +24,7 @@ Contains information about the buffer
struct Buffer
{
BUFFER_COMMON // Variables that are common to static and dynamic buffers
unsigned char *buffer; // Internal buffer
MemContext *memContext; // Mem context for dynamic buffers
};

@@ -60,11 +61,11 @@ bufNew(size_t size)
Create a new buffer from a C buffer
***********************************************************************************************************************************/
Buffer *
bufNewC(size_t size, const void *buffer)
bufNewC(const void *buffer, size_t size)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(SIZE, size);
FUNCTION_TEST_PARAM_P(VOID, buffer);
FUNCTION_TEST_PARAM(SIZE, size);
FUNCTION_TEST_END();

ASSERT(buffer != NULL);
@@ -77,6 +78,50 @@ bufNewC(size_t size, const void *buffer)
FUNCTION_TEST_RETURN(this);
}

/***********************************************************************************************************************************
Create a new buffer using the provided C buffer instead of creating one
Note that this type of buffer cannot be resized.
***********************************************************************************************************************************/
Buffer *
bufNewUseC(void *buffer, size_t size)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM_P(VOID, buffer);
FUNCTION_TEST_PARAM(SIZE, size);
FUNCTION_TEST_END();

ASSERT(buffer != NULL);

// Create object and copy data
Buffer *this = bufNew(0);
this->buffer = buffer;
this->size = size;
this->fixedSize = true;

FUNCTION_TEST_RETURN(this);
}

/***********************************************************************************************************************************
Duplicate a buffer
***********************************************************************************************************************************/
Buffer *
bufDup(const Buffer *buffer)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(BUFFER, buffer);
FUNCTION_TEST_END();

ASSERT(buffer != NULL);

// Create object and copy data
Buffer *this = bufNew(buffer->used);
memcpy(this->buffer, buffer->buffer, this->size);
this->used = this->size;

FUNCTION_TEST_RETURN(this);
}

/***********************************************************************************************************************************
Append the contents of another buffer
***********************************************************************************************************************************/
@@ -189,7 +234,7 @@ bufHex(const Buffer *this)

String *result = strNew("");

for (unsigned int bufferIdx = 0; bufferIdx < bufSize(this); bufferIdx++)
for (unsigned int bufferIdx = 0; bufferIdx < bufUsed(this); bufferIdx++)
strCatFmt(result, "%02x", this->buffer[bufferIdx]);

FUNCTION_TEST_RETURN(result);
@@ -230,6 +275,9 @@ bufResize(Buffer *this, size_t size)
// Only resize if it the new size is different
if (this->size != size)
{
if (this->fixedSize)
THROW(AssertError, "fixed size buffer cannot be resized");

// If new size is zero then free memory if allocated
if (size == 0)
{
@@ -16,7 +16,10 @@ typedef struct Buffer Buffer;
Functions
***********************************************************************************************************************************/
Buffer *bufNew(size_t size);
Buffer *bufNewC(size_t size, const void *buffer);
Buffer *bufNewC(const void *buffer, size_t size);
Buffer *bufNewUseC(void *buffer, size_t size);

Buffer *bufDup(const Buffer *buffer);

Buffer *bufCat(Buffer *this, const Buffer *cat);
Buffer *bufCatC(Buffer *this, const unsigned char *cat, size_t catOffset, size_t catSize);
@@ -49,13 +52,16 @@ functions that process dynamically allocated buffers.
#define BUFFER_COMMON \
size_t size; /* Actual size of buffer */ \
bool limitSet; /* Has a limit been set? */ \
bool fixedSize; /* Is this a fixed size buffer? */ \
size_t limit; /* Make the buffer appear smaller */ \
size_t used; /* Amount of buffer used */ \
unsigned char *buffer; /* Buffer allocation */
size_t used; /* Amount of buffer used */

typedef struct BufferConst
{
BUFFER_COMMON

// This version of buffer is for const macro assignments because casting can be dangerous
const void *buffer;
} BufferConst;

/***********************************************************************************************************************************
@@ -498,7 +498,7 @@ xmlDocumentBuf(const XmlDocument *this)
int xmlSize;

xmlDocDumpMemoryEnc(this->xml, &xml, &xmlSize, XML_ENCODING_TYPE_UTF8);
Buffer *result = bufNewC((unsigned int)xmlSize, xml);
Buffer *result = bufNewC(xml, (size_t)xmlSize);
xmlFree(xml);

FUNCTION_TEST_RETURN(result);
@@ -27,8 +27,8 @@ testCompress(GzipCompress *compress, Buffer *decompressed, size_t inputSize, siz
{
// Generate the input buffer based on input size. This breaks the data up into chunks as it would be in a real scenario.
Buffer *input = bufNewC(
inputSize > bufSize(decompressed) - inputTotal ? bufSize(decompressed) - inputTotal : inputSize,
bufPtr(decompressed) + inputTotal);
bufPtr(decompressed) + inputTotal,
inputSize > bufSize(decompressed) - inputTotal ? bufSize(decompressed) - inputTotal : inputSize);

ioWrite(write, input);

@@ -108,7 +108,7 @@ testRun(void)
{
const char *simpleData = "A simple string";
Buffer *compressed = NULL;
Buffer *decompressed = bufNewC(strlen(simpleData), simpleData);
Buffer *decompressed = bufNewC(simpleData, strlen(simpleData));

TEST_ASSIGN(
compressed, testCompress(gzipCompressNew(3, false), decompressed, 1024, 1024),
@@ -181,7 +181,7 @@ testRun(void)

bufUsedZero(decryptBuffer);

ioFilterProcessInOut(blockDecryptFilter, bufNewC(CIPHER_BLOCK_MAGIC_SIZE, bufPtr(encryptBuffer)), decryptBuffer);
ioFilterProcessInOut(blockDecryptFilter, bufNewC(bufPtr(encryptBuffer), CIPHER_BLOCK_MAGIC_SIZE), decryptBuffer);
TEST_RESULT_INT(bufUsed(decryptBuffer), 0, "no decrypt since header read is not complete");
TEST_RESULT_BOOL(blockDecrypt->saltDone, false, "salt done is false");
TEST_RESULT_BOOL(blockDecrypt->processDone, false, "process done is false");
@@ -190,7 +190,7 @@ testRun(void)
memcmp(blockDecrypt->header, CIPHER_BLOCK_MAGIC, CIPHER_BLOCK_MAGIC_SIZE) == 0, true, "check header magic");

ioFilterProcessInOut(
blockDecryptFilter, bufNewC(PKCS5_SALT_LEN, bufPtr(encryptBuffer) + CIPHER_BLOCK_MAGIC_SIZE), decryptBuffer);
blockDecryptFilter, bufNewC(bufPtr(encryptBuffer) + CIPHER_BLOCK_MAGIC_SIZE, PKCS5_SALT_LEN), decryptBuffer);
TEST_RESULT_INT(bufUsed(decryptBuffer), 0, "no decrypt since no data processed yet");
TEST_RESULT_BOOL(blockDecrypt->saltDone, true, "salt done is true");
TEST_RESULT_BOOL(blockDecrypt->processDone, false, "process done is false");
@@ -203,7 +203,7 @@ testRun(void)

ioFilterProcessInOut(
blockDecryptFilter,
bufNewC(bufUsed(encryptBuffer) - CIPHER_BLOCK_HEADER_SIZE, bufPtr(encryptBuffer) + CIPHER_BLOCK_HEADER_SIZE),
bufNewC(bufPtr(encryptBuffer) + CIPHER_BLOCK_HEADER_SIZE, bufUsed(encryptBuffer) - CIPHER_BLOCK_HEADER_SIZE),
decryptBuffer);
TEST_RESULT_INT(bufUsed(decryptBuffer), EVP_CIPHER_block_size(blockDecrypt->cipher), "decrypt size is one block");

@@ -152,7 +152,7 @@ ioTestFilterMultiplyProcess(IoTestFilterMultiply *this, const Buffer *input, Buf
else
{
char flushZ[] = {this->flushChar, 0};
bufCat(output, bufNewC(1, flushZ));
bufCat(output, bufNewC(flushZ, 1));
this->flushTotal--;
}
}
@@ -280,7 +280,7 @@ testRun(void)
// -------------------------------------------------------------------------------------------------------------------------
ioBufferSizeSet(2);
buffer = bufNew(2);
bufferOriginal = bufNewC(3, "123");
bufferOriginal = bufNewC("123", 3);

MEM_CONTEXT_TEMP_BEGIN()
{
@@ -11,7 +11,7 @@ testRun(void)
FUNCTION_HARNESS_VOID();

// *****************************************************************************************************************************
if (testBegin("bufNew(), bugNewC, bufMove(), bufSize(), bufPtr(), and bufFree()"))
if (testBegin("bufNew(), bufNewC, bufNewUseC, bufMove(), bufSize(), bufPtr(), and bufFree()"))
{
Buffer *buffer = NULL;

@@ -25,9 +25,14 @@ testRun(void)
TEST_RESULT_PTR(bufPtr(buffer), buffer->buffer, "buffer pointer");
TEST_RESULT_INT(bufSize(buffer), 256, "buffer size");

TEST_ASSIGN(buffer, bufNewC(sizeof("TEST-STR") - 1, "TEST-STR"), "new buffer from string");
TEST_ASSIGN(buffer, bufNewC("TEST-STR", sizeof("TEST-STR") - 1), "new buffer from string");
TEST_RESULT_BOOL(memcmp(bufPtr(buffer), "TEST-STR", 8) == 0, true, "check buffer");


TEST_ASSIGN(buffer, bufNewUseC((void *)"FIXED-BUFFER", sizeof("FIXED-BUFFER")), "new fixed buffer from string");
TEST_RESULT_BOOL(memcmp(bufPtr(buffer), "FIXED-BUFFER", 12) == 0, true, "check buffer");
TEST_ERROR(bufResize(buffer, 999), AssertError, "fixed size buffer cannot be resized");

TEST_RESULT_VOID(bufFree(buffer), "free buffer");
TEST_RESULT_VOID(bufFree(bufNew(0)), "free empty buffer");
TEST_RESULT_VOID(bufFree(NULL), "free null buffer");
@@ -37,7 +42,7 @@ testRun(void)
// -------------------------------------------------------------------------------------------------------------------------
char cBuffer[] = "ABCD";

TEST_ASSIGN(buffer, bufNewC(sizeof(cBuffer), cBuffer), "create from c buffer");
TEST_ASSIGN(buffer, bufNewC(cBuffer, sizeof(cBuffer)), "create from c buffer");
TEST_RESULT_BOOL(memcmp(bufPtr(buffer), cBuffer, sizeof(cBuffer)) == 0, true, "check buffer");
}

@@ -112,11 +117,11 @@ testRun(void)
}

// *****************************************************************************************************************************
if (testBegin("bufEq()"))
if (testBegin("bufDup() and bufEq()"))
{
TEST_RESULT_BOOL(bufEq(BUFSTRDEF("123"), BUFSTRDEF("1234")), false, "buffer sizes not equal");
TEST_RESULT_BOOL(bufEq(BUFSTRDEF("123"), bufDup(BUFSTRDEF("1234"))), false, "buffer sizes not equal");
TEST_RESULT_BOOL(bufEq(BUFSTR(STRDEF("321")), BUFSTRDEF("123")), false, "buffer sizes equal");
TEST_RESULT_BOOL(bufEq(BUFSTRZ("123"), BUFSTRDEF("123")), true, "buffers equal");
TEST_RESULT_BOOL(bufEq(bufDup(BUFSTRZ("123")), BUF("123", 3)), true, "buffers equal");
}

// *****************************************************************************************************************************
@@ -128,13 +133,13 @@ testRun(void)
// *****************************************************************************************************************************
if (testBegin("bufCat*()"))
{
TEST_RESULT_STR(strPtr(strNewBuf(bufCat(bufNewC(3, "123"), NULL))), "123", "cat null buffer");
TEST_RESULT_STR(strPtr(strNewBuf(bufCat(bufNewC(3, "123"), bufNew(0)))), "123", "cat empty buffer");
TEST_RESULT_STR(strPtr(strNewBuf(bufCat(bufNewC(3, "123"), BUFSTRDEF("ABC")))), "123ABC", "cat buffer");
TEST_RESULT_STR(strPtr(strNewBuf(bufCat(bufNewC("123", 3), NULL))), "123", "cat null buffer");
TEST_RESULT_STR(strPtr(strNewBuf(bufCat(bufNewC("123", 3), bufNew(0)))), "123", "cat empty buffer");
TEST_RESULT_STR(strPtr(strNewBuf(bufCat(bufNewC("123", 3), BUFSTRDEF("ABC")))), "123ABC", "cat buffer");

TEST_RESULT_STR(strPtr(strNewBuf(bufCatSub(bufNewC(3, "123"), NULL, 0, 0))), "123", "cat sub null buffer");
TEST_RESULT_STR(strPtr(strNewBuf(bufCatSub(bufNewC(3, "123"), bufNew(0), 0, 0))), "123", "cat sub empty buffer");
TEST_RESULT_STR(strPtr(strNewBuf(bufCatSub(bufNewC(3, "123"), BUFSTRDEF("ABC"), 1, 2))), "123BC", "cat sub buffer");
TEST_RESULT_STR(strPtr(strNewBuf(bufCatSub(bufNewC("123", 3), NULL, 0, 0))), "123", "cat sub null buffer");
TEST_RESULT_STR(strPtr(strNewBuf(bufCatSub(bufNewC("123", 3), bufNew(0), 0, 0))), "123", "cat sub empty buffer");
TEST_RESULT_STR(strPtr(strNewBuf(bufCatSub(bufNewC("123", 3), BUFSTRDEF("ABC"), 1, 2))), "123BC", "cat sub buffer");

Buffer *buffer = NULL;
TEST_ASSIGN(buffer, bufNew(2), "new buffer with space");
@@ -13,7 +13,7 @@ testRun(void)
// *****************************************************************************************************************************
if (testBegin("xml*()"))
{
TEST_ERROR(xmlDocumentNewBuf(bufNewC(strlen(BOGUS_STR), BOGUS_STR)), FormatError, "invalid xml");
TEST_ERROR(xmlDocumentNewBuf(bufNewC(BOGUS_STR, strlen(BOGUS_STR))), FormatError, "invalid xml");

XmlDocument *xmlDocument = NULL;
TEST_ASSIGN(

0 comments on commit 498017b

Please sign in to comment.
You can’t perform that action at this time.