Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Bug 1390129 - add PORT_ZAllocAligned function for allocationg aligned…
… memory, r=mt

Differential Revision: https://nss-review.dev.mozaws.net/D413

--HG--
extra : rebase_source : f1c794fb8501bb1f566b7ad6919e23d89695dc9b
extra : amend_source : 5f54b64b7db3a0ba096afc407ac2929db2d344c6
extra : histedit_source : 2e209927a090b8ede744de911a7a907187b0a554%2C93ce0cb26d0380edd54faf96f23703c0fa593de5
  • Loading branch information
franziskuskiefer committed Aug 16, 2017
1 parent 39e105a commit 69c0086
Show file tree
Hide file tree
Showing 11 changed files with 217 additions and 19 deletions.
82 changes: 82 additions & 0 deletions gtests/util_gtest/util_aligned_malloc_unittest.cc
@@ -0,0 +1,82 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "gtest/gtest.h"
#include "scoped_ptrs_util.h"

namespace nss_test {

struct SomeContext {
uint8_t some_buf[13];
void *mem;
};

template <class T>
struct ScopedDelete {
void operator()(T *ptr) {
if (ptr) {
PORT_Free(ptr->mem);
}
}
};
typedef std::unique_ptr<SomeContext, ScopedDelete<SomeContext> >
ScopedSomeContext;

class AlignedMallocTest : public ::testing::Test,
public ::testing::WithParamInterface<size_t> {
protected:
ScopedSomeContext test_align_new(size_t alignment) {
ScopedSomeContext ctx(PORT_ZNewAligned(SomeContext, alignment, mem));
return ctx;
};
ScopedSomeContext test_align_alloc(size_t alignment) {
void *mem = nullptr;
ScopedSomeContext ctx((SomeContext *)PORT_ZAllocAligned(sizeof(SomeContext),
alignment, &mem));
if (ctx) {
ctx->mem = mem;
}
return ctx;
}
};

TEST_P(AlignedMallocTest, TestNew) {
size_t alignment = GetParam();
ScopedSomeContext ctx = test_align_new(alignment);
EXPECT_TRUE(ctx.get());
EXPECT_EQ(0U, (uintptr_t)ctx.get() % alignment);
}

TEST_P(AlignedMallocTest, TestAlloc) {
size_t alignment = GetParam();
ScopedSomeContext ctx = test_align_alloc(alignment);
EXPECT_TRUE(ctx.get());
EXPECT_EQ(0U, (uintptr_t)ctx.get() % alignment);
}

class AlignedMallocTestBadSize : public AlignedMallocTest {};

TEST_P(AlignedMallocTestBadSize, TestNew) {
size_t alignment = GetParam();
ScopedSomeContext ctx = test_align_new(alignment);
EXPECT_FALSE(ctx.get());
}

TEST_P(AlignedMallocTestBadSize, TestAlloc) {
size_t alignment = GetParam();
ScopedSomeContext ctx = test_align_alloc(alignment);
EXPECT_FALSE(ctx.get());
}

static const size_t kSizes[] = {1, 2, 4, 8, 16, 32, 64};
static const size_t kBadSizes[] = {0, 7, 17, 24, 56};

INSTANTIATE_TEST_CASE_P(AllAligned, AlignedMallocTest,
::testing::ValuesIn(kSizes));
INSTANTIATE_TEST_CASE_P(AllAlignedBadSize, AlignedMallocTestBadSize,
::testing::ValuesIn(kBadSizes));

} // namespace nss_test
1 change: 1 addition & 0 deletions gtests/util_gtest/util_gtest.gyp
Expand Up @@ -14,6 +14,7 @@
'util_utf8_unittest.cc',
'util_b64_unittest.cc',
'util_pkcs11uri_unittest.cc',
'util_aligned_malloc_unittest.cc',
'<(DEPTH)/gtests/common/gtests.cc',
],
'dependencies': [
Expand Down
11 changes: 2 additions & 9 deletions lib/freebl/gcm.c
Expand Up @@ -574,7 +574,7 @@ GCM_CreateContext(void *context, freeblCipherFunc cipher,
const unsigned char *params)
{
GCMContext *gcm = NULL;
gcmHashContext *ghash = NULL, *ghashmem = NULL;
gcmHashContext *ghash = NULL;
unsigned char H[MAX_BLOCK_SIZE];
unsigned int tmp;
PRBool freeCtr = PR_FALSE;
Expand All @@ -595,14 +595,7 @@ GCM_CreateContext(void *context, freeblCipherFunc cipher,
if (gcm == NULL) {
return NULL;
}
/* aligned_alloc is C11 so we have to do it the old way. */
ghashmem = PORT_ZAlloc(sizeof(gcmHashContext) + 15);
if (ghashmem == NULL) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
goto loser;
}
ghash = (gcmHashContext *)(((uintptr_t)ghashmem + 15) & ~(uintptr_t)0x0F);
ghash->mem = ghashmem;
ghash = PORT_ZNewAligned(gcmHashContext, 16, mem);

/* first plug in the ghash context */
gcm->ghash_context = ghash;
Expand Down
11 changes: 1 addition & 10 deletions lib/freebl/rijndael.c
Expand Up @@ -1017,16 +1017,7 @@ rijndael_decryptCBC(AESContext *cx, unsigned char *output,
AESContext *
AES_AllocateContext(void)
{
/* aligned_alloc is C11 so we have to do it the old way. */
AESContext *ctx, *ctxmem;
ctxmem = PORT_ZAlloc(sizeof(AESContext) + 15);
if (ctxmem == NULL) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
return NULL;
}
ctx = (AESContext *)(((uintptr_t)ctxmem + 15) & ~(uintptr_t)0x0F);
ctx->mem = ctxmem;
return ctx;
return PORT_ZNewAligned(AESContext, 16, mem);
}

/*
Expand Down
53 changes: 53 additions & 0 deletions lib/freebl/stubs.c
Expand Up @@ -136,6 +136,11 @@ STUB_DECLARE(int, PORT_GetError_Util, (void));
STUB_DECLARE(PLArenaPool *, PORT_NewArena_Util, (unsigned long chunksize));
STUB_DECLARE(void, PORT_SetError_Util, (int value));
STUB_DECLARE(void *, PORT_ZAlloc_Util, (size_t len));
STUB_DECLARE(void *, PORT_ZAllocAligned_Util, (size_t bytes, size_t alignment,
void **mem));
STUB_DECLARE(void *, PORT_ZAllocAlignedOffset_Util, (size_t bytes,
size_t alignment,
size_t offset));
STUB_DECLARE(void, PORT_ZFree_Util, (void *ptr, size_t len));

STUB_DECLARE(void, PR_Assert, (const char *s, const char *file, PRIntn ln));
Expand Down Expand Up @@ -179,6 +184,8 @@ STUB_DECLARE(int, NSS_SecureMemcmp, (const void *a, const void *b, size_t n));
#define PORT_New_stub(type) (type *)PORT_Alloc_stub(sizeof(type))
#define PORT_ZNewArray_stub(type, num) \
(type *)PORT_ZAlloc_stub(sizeof(type) * (num))
#define PORT_ZNewAligned_stub(type, alignment, mem) \
(type *)PORT_ZAllocAlignedOffset_stub(sizeof(type), alignment, offsetof(type, mem))

/*
* NOTE: in order to support hashing only the memory allocation stubs,
Expand Down Expand Up @@ -214,6 +221,52 @@ PORT_ZAlloc_stub(size_t len)
return ptr;
}

/* aligned_alloc is C11. This is an alternative to get aligned memory. */
extern void *
PORT_ZAllocAligned_stub(size_t bytes, size_t alignment, void **mem)
{
STUB_SAFE_CALL3(PORT_ZAllocAligned_Util, bytes, alignment, mem);

/* This only works if alignement is a power of 2. */
if ((alignment == 0) || (alignment & (alignment - 1))) {
return NULL;
}

size_t x = alignment - 1;
size_t len = (bytes ? bytes : 1) + x;

if (!mem) {
return NULL;
}

/* Always allocate a non-zero amount of bytes */
*mem = malloc(len);
if (!*mem) {
return NULL;
}

memset(*mem, 0, len);
return (void *)(((uintptr_t)*mem + x) & ~(uintptr_t)x);
}

extern void *
PORT_ZAllocAlignedOffset_stub(size_t size, size_t alignment, size_t offset)
{
STUB_SAFE_CALL3(PORT_ZAllocAlignedOffset_Util, size, alignment, offset);
if (offset > size) {
return NULL;
}

void *mem = NULL;
void *v = PORT_ZAllocAligned_stub(size, alignment, &mem);
if (!v) {
return NULL;
}

*((void **)((uintptr_t)v + offset)) = mem;
return v;
}

extern void
PORT_ZFree_stub(void *ptr, size_t len)
{
Expand Down
2 changes: 2 additions & 0 deletions lib/freebl/stubs.h
Expand Up @@ -30,6 +30,8 @@
#define PORT_SetError PORT_SetError_stub
#define PORT_ZAlloc PORT_ZAlloc_stub
#define PORT_ZFree PORT_ZFree_stub
#define PORT_ZAllocAligned PORT_ZAllocAligned_stub
#define PORT_ZAllocAlignedOffset PORT_ZAllocAlignedOffset_stub

#define SECITEM_AllocItem SECITEM_AllocItem_stub
#define SECITEM_CompareItem SECITEM_CompareItem_stub
Expand Down
14 changes: 14 additions & 0 deletions lib/nss/utilwrap.c
Expand Up @@ -75,6 +75,8 @@
#undef PORT_UCS2_ASCIIConversion
#undef PORT_UCS2_UTF8Conversion
#undef PORT_ZAlloc
#undef PORT_ZAllocAligned
#undef PORT_ZAllocAlignedOffset
#undef PORT_ZFree
#undef SEC_ASN1Decode
#undef SEC_ASN1DecodeInteger
Expand Down Expand Up @@ -144,6 +146,18 @@ PORT_ZAlloc(size_t bytes)
return PORT_ZAlloc_Util(bytes);
}

void *
PORT_ZAllocAligned(size_t bytes, size_t alignment, void **mem)
{
return PORT_ZAllocAligned_Util(bytes, alignment, mem);
}

void *
PORT_ZAllocAlignedOffset(size_t bytes, size_t alignment, size_t offset)
{
return PORT_ZAllocAlignedOffset_Util(bytes, alignment, offset);
}

void
PORT_Free(void *ptr)
{
Expand Down
7 changes: 7 additions & 0 deletions lib/util/nssutil.def
Expand Up @@ -307,3 +307,10 @@ PK11URI_GetQueryAttribute;
;+ local:
;+ *;
;+};
;+NSSUTIL_3.33 { # NSS Utilities 3.33 release
;+ global:
PORT_ZAllocAligned_Util;
PORT_ZAllocAlignedOffset_Util;
;+ local:
;+ *;
;+};
47 changes: 47 additions & 0 deletions lib/util/secport.c
Expand Up @@ -21,6 +21,8 @@
#include "prenv.h"
#include "prinit.h"

#include <stdint.h>

#ifdef DEBUG
#define THREADMARK
#endif /* DEBUG */
Expand Down Expand Up @@ -119,6 +121,51 @@ PORT_ZAlloc(size_t bytes)
return rv;
}

/* aligned_alloc is C11. This is an alternative to get aligned memory. */
void *
PORT_ZAllocAligned(size_t bytes, size_t alignment, void **mem)
{
size_t x = alignment - 1;

/* This only works if alignment is a power of 2. */
if ((alignment == 0) || (alignment & (alignment - 1))) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}

if (!mem) {
return NULL;
}

/* Always allocate a non-zero amount of bytes */
*mem = PORT_ZAlloc((bytes ? bytes : 1) + x);
if (!*mem) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
return NULL;
}

return (void *)(((uintptr_t)*mem + x) & ~(uintptr_t)x);
}

void *
PORT_ZAllocAlignedOffset(size_t size, size_t alignment, size_t offset)
{
PORT_Assert(offset < size);
if (offset > size) {
return NULL;
}

void *mem = NULL;
void *v = PORT_ZAllocAligned(size, alignment, &mem);
if (!v) {
return NULL;
}

PORT_Assert(mem);
*((void **)((uintptr_t)v + offset)) = mem;
return v;
}

void
PORT_Free(void *ptr)
{
Expand Down
6 changes: 6 additions & 0 deletions lib/util/secport.h
Expand Up @@ -45,6 +45,7 @@
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>
#include "prtypes.h"
#include "prlog.h" /* for PR_ASSERT */
#include "plarena.h"
Expand Down Expand Up @@ -88,6 +89,9 @@ SEC_BEGIN_PROTOS
extern void *PORT_Alloc(size_t len);
extern void *PORT_Realloc(void *old, size_t len);
extern void *PORT_ZAlloc(size_t len);
extern void *PORT_ZAllocAligned(size_t bytes, size_t alignment, void **mem);
extern void *PORT_ZAllocAlignedOffset(size_t bytes, size_t alignment,
size_t offset);
extern void PORT_Free(void *ptr);
extern void PORT_ZFree(void *ptr, size_t len);
extern char *PORT_Strdup(const char *s);
Expand Down Expand Up @@ -131,6 +135,8 @@ SEC_END_PROTOS
#define PORT_CheckSuccess(f) (f)
#endif
#define PORT_ZNew(type) (type *)PORT_ZAlloc(sizeof(type))
#define PORT_ZNewAligned(type, alignment, mem) \
(type *)PORT_ZAllocAlignedOffset(sizeof(type), alignment, offsetof(type, mem))
#define PORT_New(type) (type *)PORT_Alloc(sizeof(type))
#define PORT_ArenaNew(poolp, type) \
(type *)PORT_ArenaAlloc(poolp, sizeof(type))
Expand Down
2 changes: 2 additions & 0 deletions lib/util/utilrename.h
Expand Up @@ -70,6 +70,8 @@
#define PORT_UCS2_ASCIIConversion PORT_UCS2_ASCIIConversion_Util
#define PORT_UCS2_UTF8Conversion PORT_UCS2_UTF8Conversion_Util
#define PORT_ZAlloc PORT_ZAlloc_Util
#define PORT_ZAllocAligned PORT_ZAllocAligned_Util
#define PORT_ZAllocAlignedOffset PORT_ZAllocAlignedOffset_Util
#define PORT_ZFree PORT_ZFree_Util
#define SEC_ASN1Decode SEC_ASN1Decode_Util
#define SEC_ASN1DecodeInteger SEC_ASN1DecodeInteger_Util
Expand Down

0 comments on commit 69c0086

Please sign in to comment.