Index: /trunk/include/iprt/memsafer.h
===================================================================
--- /trunk/include/iprt/memsafer.h	(revision 52017)
+++ /trunk/include/iprt/memsafer.h	(revision 52018)
@@ -57,4 +57,10 @@
  */
 
+/** Default memory allocation, non-pageable memory backing, return error
+ * if not possible to allocate such memor. */
+#define RTMEMSAFER_ALLOC_EX_FLAGS_DEFAULT                   (0)
+/** Allow pageable memory backing for cases where the content is not that sensitive
+ * and allocating non-pageable memory failes. Use with care! */
+#define RTMEMSAFER_ALLOC_EX_ALLOW_PAGEABLE_BACKING RT_BIT_32(1)
 
 /**
@@ -96,7 +102,8 @@
  * @param   ppvNew      Where to return the pointer to the memory.
  * @param   cb          Number of bytes to allocate.
- * @param   pszTag      Allocation tag used for statistics and such.
- */
-RTDECL(int) RTMemSaferAllocZExTag(void **ppvNew, size_t cb, const char *pszTag) RT_NO_THROW;
+ * @param   fFlags      Flags for controlling the allocation. See RTMEMSAFER_ALLOC_EX_FLAGS_* defines.
+ * @param   pszTag      Allocation tag used for statistics and such.
+ */
+RTDECL(int) RTMemSaferAllocZExTag(void **ppvNew, size_t cb, uint32_t fFlags, const char *pszTag) RT_NO_THROW;
 
 /**
@@ -109,6 +116,7 @@
  * @param   a_ppvNew    Where to return the pointer to the memory.
  * @param   a_cb        Number of bytes to allocate.
- */
-#define RTMemSaferAllocZEx(a_ppvNew, a_cb) RTMemSaferAllocZExTag(a_ppvNew, a_cb, RTMEM_TAG)
+ * @param   a_fFlags    Flags for controlling the allocation. See RTMEMSAFER_ALLOC_EX_FLAGS_* defines.
+ */
+#define RTMemSaferAllocZEx(a_ppvNew, a_cb, a_fFlags) RTMemSaferAllocZExTag(a_ppvNew, a_cb, a_fFlags, RTMEM_TAG)
 
 /**
@@ -151,7 +159,10 @@
  * @param   cbNew       The size of the new allocation.
  * @param   ppvNew      Where to return the pointer to the new memory.
- * @param   pszTag      Allocation tag used for statistics and such.
- */
-RTDECL(int) RTMemSaferReallocZExTag(size_t cbOld, void *pvOld, size_t cbNew, void **ppvNew, const char *pszTag) RT_NO_THROW;
+ * @param   fFlags      Flags for controlling the allocation. See RTMEMSAFER_ALLOC_EX_FLAGS_* defines,
+ *                      this takes only effect when allocating completely new memory, for extending or
+ *                      shrinking existing allocations the flags of the allocation take precedence.
+ * @param   pszTag      Allocation tag used for statistics and such.
+ */
+RTDECL(int) RTMemSaferReallocZExTag(size_t cbOld, void *pvOld, size_t cbNew, void **ppvNew, uint32_t fFlags, const char *pszTag) RT_NO_THROW;
 
 /**
@@ -170,7 +181,10 @@
  * @param   a_cbNew     The size of the new allocation.
  * @param   a_ppvNew    Where to return the pointer to the new memory.
- */
-#define RTMemSaferReallocZEx(a_cbOld, a_pvOld, a_cbNew, a_ppvNew) \
-    RTMemSaferReallocZExTag(a_cbOld, a_pvOld, a_cbNew, a_ppvNew, RTMEM_TAG)
+ * @param   a_fFlags    Flags for controlling the allocation. See RTMEMSAFER_ALLOC_EX_FLAGS_* defines,
+ *                      this takes only effect when allocating completely new memory, for extending or
+ *                      shrinking existing allocations the flags of the allocation take precedence.
+ */
+#define RTMemSaferReallocZEx(a_cbOld, a_pvOld, a_cbNew, a_ppvNew, a_fFlags) \
+    RTMemSaferReallocZExTag(a_cbOld, a_pvOld, a_cbNew, a_ppvNew, a_fFlags, RTMEM_TAG)
 
 /**
Index: /trunk/src/VBox/Runtime/common/math/bignum.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/math/bignum.cpp	(revision 52017)
+++ /trunk/src/VBox/Runtime/common/math/bignum.cpp	(revision 52018)
@@ -118,7 +118,10 @@
     Assert(cbNew > cbOld);
 
-    void *pvNew;
+    void *pvNew = NULL;
     if (pBigNum->fSensitive)
-        pvNew = RTMemSaferReallocZ(cbOld, pBigNum->pauElements, cbNew);
+    {
+        int rc = RTMemSaferReallocZEx(cbOld, pBigNum->pauElements, cbNew, &pvNew, RTMEMSAFER_ALLOC_EX_ALLOW_PAGEABLE_BACKING);
+        Assert(VALID_PTR(pvNew) || RT_FAILURE(rc));
+    }
     else
         pvNew = RTMemRealloc(pBigNum->pauElements, cbNew);
@@ -323,5 +326,9 @@
         pBigNum->cAllocated = RT_ALIGN_32(pBigNum->cUsed, 4);
         if (pBigNum->fSensitive)
-            pBigNum->pauElements = (RTBIGNUMELEMENT *)RTMemSaferAllocZ(pBigNum->cAllocated * RTBIGNUM_ELEMENT_SIZE);
+        {
+            int rc = RTMemSaferAllocZEx((void **)&pBigNum->pauElements, pBigNum->cAllocated * RTBIGNUM_ELEMENT_SIZE,
+                                        RTMEMSAFER_ALLOC_EX_ALLOW_PAGEABLE_BACKING);
+            Assert(VALID_PTR(pBigNum->pauElements) || RT_FAILURE(rc));
+        }
         else
             pBigNum->pauElements = (RTBIGNUMELEMENT *)RTMemAlloc(pBigNum->cAllocated * RTBIGNUM_ELEMENT_SIZE);
@@ -457,5 +464,9 @@
         pBigNum->cAllocated = RT_ALIGN_32(pBigNum->cUsed, 4);
         if (pBigNum->fSensitive)
-            pBigNum->pauElements = (RTBIGNUMELEMENT *)RTMemSaferAllocZ(pBigNum->cAllocated * RTBIGNUM_ELEMENT_SIZE);
+        {
+            rc = RTMemSaferAllocZEx((void **)&pBigNum->pauElements, pBigNum->cAllocated * RTBIGNUM_ELEMENT_SIZE,
+                                    RTMEMSAFER_ALLOC_EX_ALLOW_PAGEABLE_BACKING);
+            Assert(VALID_PTR(pBigNum->pauElements) || RT_FAILURE(rc));
+        }
         else
             pBigNum->pauElements = (RTBIGNUMELEMENT *)RTMemAlloc(pBigNum->cAllocated * RTBIGNUM_ELEMENT_SIZE);
Index: /trunk/src/VBox/Runtime/generic/memsafer-generic.cpp
===================================================================
--- /trunk/src/VBox/Runtime/generic/memsafer-generic.cpp	(revision 52017)
+++ /trunk/src/VBox/Runtime/generic/memsafer-generic.cpp	(revision 52018)
@@ -34,4 +34,8 @@
 #include <iprt/assert.h>
 #include <iprt/string.h>
+#if defined(IN_SUP_R3) && defined(VBOX) && !defined(RT_NO_GIP)
+# include <iprt/param.h>
+# include <VBox/sup.h>
+#endif /* IN_SUP_R3 */
 
 
@@ -46,9 +50,49 @@
 #define RTMEMSAFER_PAD_AFTER    32
 
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+
+/**
+ * Supported allocation methods.
+ */
+typedef enum RTMEMSAFERALLOCMETHOD
+{
+    /** Invalid method. */
+    RTMEMSAFERALLOCMETHOD_INVALID = 0,
+    /** RTMem{Alloc|Free} methods, least secure!. */
+    RTMEMSAFERALLOCMETHOD_RTMEM,
+    /** Support library. */
+    RTMEMSAFERALLOCMETHOD_SUPR3,
+    /** 32bit hack. */
+    RTMEMSAFERALLOCMETHOD_32BIT_HACK = 0x7fffffff
+} RTMEMSAFERALLOCMETHOD;
+/** Pointer to a allocation method enum. */
+typedef RTMEMSAFERALLOCMETHOD *PRTMEMSAFERALLOCMETHOD;
+
+/**
+ * Memory header for safer memory allocations.
+ *
+ * @note: There is no magic value used deliberately to make identifying this structure
+ *        as hard as possible.
+ */
+typedef struct RTMEMSAFERHDR
+{
+    /** Flags passed to this allocation - used for freeing and reallocation. */
+    uint32_t              fFlags;
+    /** Allocation method used. */
+    RTMEMSAFERALLOCMETHOD enmAllocMethod;
+    /** Amount of bytes allocated. */
+    size_t                cb;
+} RTMEMSAFERHDR;
+/** Pointer to a safer memory header. */
+typedef RTMEMSAFERHDR *PRTMEMSAFERHDR;
+/** Make sure we are staying in the padding area. */
+AssertCompile(sizeof(RTMEMSAFERHDR) < RTMEMSAFER_PAD_BEFORE);
 
 /*******************************************************************************
 *   Global Variables                                                           *
 *******************************************************************************/
-/** XOR scrabler value.
+/** XOR scrambler value.
  * @todo determine this at runtime */
 #if ARCH_BITS == 32
@@ -62,9 +106,79 @@
 
 
+/**
+ * Support (SUPR3) based allocator.
+ *
+ * @returns VBox status code.
+ * @retval VERR_NOT_SUPPORTED if this allocation method is not supported in this
+ *         version of the library.
+ * @param  ppvNew    Where to store the pointer to the new buffer on success.
+ * @param  cb        Amount of bytes to allocate.
+ *
+ * @note: The allocation will have an extra page allocated before and after the
+ *        user area with all access rights removed to prevent heartbleed like
+ *        attacks.
+ */
+static int rtMemSaferSupR3Alloc(void **ppvNew, size_t cb)
+{
+#if defined(IN_SUP_R3) && defined(VBOX) && !defined(RT_NO_GIP)
+    /*
+     * Allocate locked memory from the support library.
+     * 
+     */
+    size_t cbUser = RT_ALIGN_Z(cb, PAGE_SIZE);
+    size_t cPages = cbUser / PAGE_SIZE + 2; /* For the extra guarding pages. */
+    void *pvNew = NULL;
+    int rc = SUPR3PageAllocEx(cPages, 0 /* fFlags */, &pvNew, NULL /* pR0Ptr */, NULL /* paPages */);
+    if (RT_SUCCESS(rc))
+    {
+        /* Change the memory protection of the pages guarding the allocation. */
+        rc = SUPR3PageProtect(pvNew, NIL_RTR0PTR, 0, PAGE_SIZE, RTMEM_PROT_NONE);
+        if (RT_SUCCESS(rc))
+        {
+            rc = SUPR3PageProtect(pvNew, NIL_RTR0PTR, PAGE_SIZE + cbUser, PAGE_SIZE, RTMEM_PROT_NONE);
+            if (RT_SUCCESS(rc))
+            {
+                *ppvNew = (uint8_t *)pvNew + PAGE_SIZE;
+                return VINF_SUCCESS;
+            }
+        }
+
+        rc = SUPR3PageFreeEx(pvNew, cPages);
+        AssertRC(rc);
+    }
+
+    return rc;
+#else
+    return VERR_NOT_SUPPORTED;
+#endif
+}
+
+
+/**
+ * Free method for memory allocated using the Support (SUPR3) based allocator.
+ *
+ * @returns nothing.
+ * @param   pv    Pointer to the memory to free.
+ * @param   cb    Amount of bytes allocated.
+ */
+static void rtMemSafeSupR3Free(void *pv, size_t cb)
+{
+#if defined(IN_SUP_R3) && defined(VBOX) && !defined(RT_NO_GIP)
+    size_t cbUser = RT_ALIGN_Z(cb, PAGE_SIZE);
+    size_t cPages = cbUser / PAGE_SIZE + 2; /* For the extra pages. */
+    void *pvStart = (uint8_t *)pv - PAGE_SIZE;
+
+    int rc = SUPR3PageFreeEx(pvStart, cPages);
+    AssertRC(rc);
+#else
+    AssertMsgFailed(("SUPR3 allocated memory but freeing is not supported, messed up\n"));
+#endif
+}
+
+
 RTDECL(int) RTMemSaferScramble(void *pv, size_t cb)
 {
-
-    AssertMsg(*(size_t *)((char *)pv - RTMEMSAFER_PAD_BEFORE) == cb,
-              ("*pvStart=%#zx cb=%#zx\n", *(size_t *)((char *)pv- RTMEMSAFER_PAD_BEFORE), cb));
+    PRTMEMSAFERHDR pHdr = (PRTMEMSAFERHDR)((char *)pv - RTMEMSAFER_PAD_BEFORE);
+    AssertMsg(pHdr->cb == cb, ("pHdr->cb=%#zx cb=%#zx\n", pHdr->cb, cb));
 
     /* Note! This isn't supposed to be safe, just less obvious. */
@@ -85,6 +199,6 @@
 RTDECL(int) RTMemSaferUnscramble(void *pv, size_t cb)
 {
-    AssertMsg(*(size_t *)((char *)pv - RTMEMSAFER_PAD_BEFORE) == cb,
-              ("*pvStart=%#zx cb=%#zx\n", *(size_t *)((char *)pv - RTMEMSAFER_PAD_BEFORE), cb));
+    PRTMEMSAFERHDR pHdr = (PRTMEMSAFERHDR)((char *)pv - RTMEMSAFER_PAD_BEFORE);
+    AssertMsg(pHdr->cb == cb, ("pHdr->cb=%#zx cb=%#zx\n", pHdr->cb, cb));
 
     /* Note! This isn't supposed to be safe, just less obvious. */
@@ -103,5 +217,5 @@
 
 
-RTDECL(int) RTMemSaferAllocZExTag(void **ppvNew, size_t cb, const char *pszTag) RT_NO_THROW
+RTDECL(int) RTMemSaferAllocZExTag(void **ppvNew, size_t cb, uint32_t fFlags, const char *pszTag) RT_NO_THROW
 {
     AssertReturn(cb, VERR_INVALID_PARAMETER);
@@ -111,14 +225,27 @@
     /*
      * Don't request zeroed memory.  We want random heap garbage in the
-     * padding zones, notthing that makes our allocations easier to find.
+     * padding zones, nothing that makes our allocations easier to find.
      */
+    RTMEMSAFERALLOCMETHOD enmAllocMethod = RTMEMSAFERALLOCMETHOD_SUPR3;
     size_t cbUser = RT_ALIGN_Z(cb, RTMEMSAFER_ALIGN);
-    void *pvNew = RTMemAlloc(cbUser + RTMEMSAFER_PAD_BEFORE + RTMEMSAFER_PAD_AFTER);
+    void *pvNew = NULL;
+    int rc = rtMemSaferSupR3Alloc(&pvNew, cbUser + RTMEMSAFER_PAD_BEFORE + RTMEMSAFER_PAD_AFTER);
+    if (   RT_FAILURE(rc)
+        && fFlags & RTMEMSAFER_ALLOC_EX_ALLOW_PAGEABLE_BACKING)
+    {
+        /* Pageable memory allowed. */
+        enmAllocMethod = RTMEMSAFERALLOCMETHOD_RTMEM;
+        pvNew = RTMemAlloc(cbUser + RTMEMSAFER_PAD_BEFORE + RTMEMSAFER_PAD_AFTER);
+    }
+
     if (pvNew)
     {
-#ifdef RT_STRICT /* For checking input in string builds. */
-        memset(pvNew, 0xad, RTMEMSAFER_PAD_BEFORE);
+        PRTMEMSAFERHDR pHdr = (PRTMEMSAFERHDR)pvNew;
+        pHdr->fFlags         = fFlags;
+        pHdr->cb             = cb;
+        pHdr->enmAllocMethod = enmAllocMethod;
+#ifdef RT_STRICT /* For checking input in strict builds. */
+        memset((char *)pvNew + sizeof(RTMEMSAFERHDR), 0xad, RTMEMSAFER_PAD_BEFORE - sizeof(RTMEMSAFERHDR));
         memset((char *)pvNew + RTMEMSAFER_PAD_BEFORE + cb, 0xda, RTMEMSAFER_PAD_AFTER + (cbUser - cb));
-        *(size_t *)pvNew = cb;
 #endif
 
@@ -131,5 +258,5 @@
         return VINF_SUCCESS;
     }
-    return VERR_NO_MEMORY;
+    return rc;
 }
 RT_EXPORT_SYMBOL(RTMemSaferAllocZExTag);
@@ -141,8 +268,23 @@
     {
         Assert(cb);
+
+        size_t cbUser = RT_ALIGN_Z(cb, RTMEMSAFER_ALIGN);
         void *pvStart = (char *)pv - RTMEMSAFER_PAD_BEFORE;
-        AssertMsg(*(size_t *)pvStart == cb, ("*pvStart=%#zx cb=%#zx\n", *(size_t *)pvStart, cb));
+        PRTMEMSAFERHDR pHdr = (PRTMEMSAFERHDR)pvStart;
+        AssertMsg(pHdr->cb == cb, ("pHdr->cb=%#zx cb=%#zx\n", pHdr->cb, cb));
+
         RTMemWipeThoroughly(pv, RT_ALIGN_Z(cb, RTMEMSAFER_ALIGN), 3);
-        RTMemFree(pvStart);
+
+        switch (pHdr->enmAllocMethod)
+        {
+            case RTMEMSAFERALLOCMETHOD_SUPR3:
+                rtMemSafeSupR3Free(pvStart, cbUser + RTMEMSAFER_PAD_BEFORE + RTMEMSAFER_PAD_AFTER);
+                break;
+            case RTMEMSAFERALLOCMETHOD_RTMEM:
+                RTMemFree(pvStart);
+                break;
+            default:
+                AssertMsgFailed(("Invalid allocation method, corrupted header\n"));
+        }
     }
     else
@@ -152,5 +294,5 @@
 
 
-RTDECL(int) RTMemSaferReallocZExTag(size_t cbOld, void *pvOld, size_t cbNew, void **ppvNew, const char *pszTag) RT_NO_THROW
+RTDECL(int) RTMemSaferReallocZExTag(size_t cbOld, void *pvOld, size_t cbNew, void **ppvNew, uint32_t fFlags, const char *pszTag) RT_NO_THROW
 {
     /*
@@ -163,4 +305,5 @@
     if (cbNew && cbOld)
     {
+        PRTMEMSAFERHDR pHdr = (PRTMEMSAFERHDR)((char *)pvOld - RTMEMSAFER_PAD_BEFORE);
         AssertPtr(pvOld);
         AssertMsg(*(size_t *)((char *)pvOld - RTMEMSAFER_PAD_BEFORE) == cbOld,
@@ -168,5 +311,5 @@
 
         void *pvNew;
-        rc = RTMemSaferAllocZExTag(&pvNew, cbNew, pszTag);
+        rc = RTMemSaferAllocZExTag(&pvNew, cbNew, pHdr->fFlags, pszTag);
         if (RT_SUCCESS(rc))
         {
@@ -180,5 +323,5 @@
     {
         Assert(pvOld == NULL);
-        rc = RTMemSaferAllocZExTag(ppvNew, cbNew, pszTag);
+        rc = RTMemSaferAllocZExTag(ppvNew, cbNew, fFlags, pszTag);
     }
     /* Free operation*/
@@ -196,5 +339,5 @@
 {
     void *pvNew = NULL;
-    int rc = RTMemSaferAllocZExTag(&pvNew, cb, pszTag);
+    int rc = RTMemSaferAllocZExTag(&pvNew, cb, RTMEMSAFER_ALLOC_EX_FLAGS_DEFAULT, pszTag);
     if (RT_SUCCESS(rc))
         return pvNew;
@@ -207,5 +350,5 @@
 {
     void *pvNew = NULL;
-    int rc = RTMemSaferReallocZExTag(cbOld, pvOld, cbNew, &pvNew, pszTag);
+    int rc = RTMemSaferReallocZExTag(cbOld, pvOld, cbNew, &pvNew, RTMEMSAFER_ALLOC_EX_FLAGS_DEFAULT, pszTag);
     if (RT_SUCCESS(rc))
         return pvNew;
Index: /trunk/src/VBox/Runtime/testcase/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Runtime/testcase/Makefile.kmk	(revision 52017)
+++ /trunk/src/VBox/Runtime/testcase/Makefile.kmk	(revision 52018)
@@ -90,4 +90,5 @@
 	tstRTMemPool \
 	tstRTMemWipe \
+	tstRTMemSafer \
 	tstMove \
 	tstRTMp-1 \
@@ -456,4 +457,7 @@
 tstRTMemWipe_SOURCES = tstRTMemWipe.cpp
 
+tstRTMemSafer_TEMPLATE = VBOXR3TSTEXE
+tstRTMemSafer_SOURCES = tstRTMemSafer.cpp
+
 tstMove_TEMPLATE = VBOXR3TSTEXE
 tstMove_SOURCES = tstMove.cpp
Index: /trunk/src/VBox/Runtime/testcase/tstRTMemSafer.cpp
===================================================================
--- /trunk/src/VBox/Runtime/testcase/tstRTMemSafer.cpp	(revision 52018)
+++ /trunk/src/VBox/Runtime/testcase/tstRTMemSafer.cpp	(revision 52018)
@@ -0,0 +1,122 @@
+/* $Id$ */
+/** @file
+ * IPRT Testcase - RTMemSafer* functions.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <iprt/path.h>
+#include <iprt/rand.h>
+#include <iprt/string.h>
+#include <iprt/stream.h>
+#include <iprt/initterm.h>
+#include <iprt/param.h>
+#include <iprt/memsafer.h>
+#include <iprt/test.h>
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+
+static void doMemSaferScramble(RTTEST hTest, void *pvBuf, size_t cbAlloc)
+{
+    RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Testing scrambling (%u bytes) ...\n", cbAlloc);
+
+    RTRandBytes(pvBuf, cbAlloc);
+
+    void *pvRef = RTMemDup(pvBuf, cbAlloc);
+    if (!pvRef)
+    {
+        RTTestIFailed("No memory for reference buffer (%z bytes)\n", cbAlloc);
+        return;
+    }
+
+    int rc = RTMemSaferScramble(pvBuf, cbAlloc);
+    if (RT_SUCCESS(rc))
+    {
+        if (!memcmp(pvRef, pvBuf, cbAlloc))
+            RTTestIFailed("Memory blocks must differ (%z bytes, 0x%p vs. 0x%p)!\n",
+                          cbAlloc, pvRef, pvBuf);
+        else
+        {
+            /* Test unscrambling. */
+            rc = RTMemSaferUnscramble(pvBuf, cbAlloc);
+            if (RT_SUCCESS(rc))
+            {
+                if (memcmp(pvRef, pvBuf, cbAlloc))
+                    RTTestIFailed("Memory blocks must not differ (%z bytes, 0x%p vs. 0x%p)!\n",
+                                  cbAlloc, pvRef, pvBuf);
+            }
+            else
+                RTTestIFailed("Unscrambling %z bytes failed with %Rrc!\n", cbAlloc, rc);
+        }
+    }
+    else
+        RTTestIFailed("Scrambling %z bytes failed with %Rrc!\n", cbAlloc, rc);
+
+    RTMemFree(pvRef);
+}
+
+static void doMemSaferAllocation(RTTEST hTest)
+{
+    size_t cbAlloc = RTRandS32Ex(1, _1M) * sizeof(uint8_t);
+
+    RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Testing allocation of secure memory (%u bytes) ...\n", cbAlloc);
+    void *pvBuf = NULL;
+    int rc = RTMemSaferAllocZEx(&pvBuf, cbAlloc, RTMEMSAFER_ALLOC_EX_FLAGS_DEFAULT);
+    if (RT_SUCCESS(rc))
+    {
+        /* Try to access memory. */
+        RTRandBytes(pvBuf, cbAlloc);
+
+        /* Scrambling test */
+        doMemSaferScramble(hTest, pvBuf, cbAlloc);
+
+#if 0
+        /* Try to access memory after the allocation, should crash. */
+        size_t cbAllocAligned = RT_ALIGN_Z(cbAlloc, PAGE_SIZE);
+        *((uint8_t *)pvBuf + cbAllocAligned) = 0xcc;
+#endif
+        RTMemSaferFree(pvBuf, cbAlloc);
+    }
+    else
+        RTTestIFailed("Allocating %z bytes of secure memory failed with %Rrc\n", cbAlloc, rc);
+}
+
+int main()
+{
+    RTTEST hTest;
+    RTEXITCODE rcExit = RTTestInitAndCreate("memsafer", &hTest);
+    if (rcExit != RTEXITCODE_SUCCESS)
+        return rcExit;
+    RTTestBanner(hTest);
+
+    doMemSaferAllocation(hTest);
+
+    return RTTestSummaryAndDestroy(hTest);
+}
+
