From 7c8548ee26cdb9152c9c5edbb352936eee517409 Mon Sep 17 00:00:00 2001 From: deadwood Date: Tue, 3 Jun 2014 16:40:14 +0000 Subject: [PATCH] exec.library: return NULL for 0-sized allocation regardless of memory manager used This follows the API guarantees as tested on OS 3.x, OS 4.x and MorphOS git-svn-id: https://svn.aros.org/svn/aros/trunk/AROS@49043 fb15a70f-31f2-0310-bbcc-cdcc74a49acc --- rom/exec/allocmem.c | 2 +- rom/exec/allocpooled.c | 4 ++++ rom/exec/allocvec.c | 4 ++++ rom/exec/allocvecpooled.c | 6 +++++- rom/exec/freemem.c | 2 +- rom/exec/freepooled.c | 4 ++++ rom/exec/freevec.c | 13 ++++++------ rom/exec/freevecpooled.c | 4 ++++ test/exec/allocxxx.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++ test/exec/mmakefile.src | 1 + test/exec/test.h | 29 +++++++++++++++++++++++++ 11 files changed, 114 insertions(+), 9 deletions(-) create mode 100644 test/exec/allocxxx.c create mode 100644 test/exec/test.h diff --git a/rom/exec/allocmem.c b/rom/exec/allocmem.c index 4f44e9fa7f..93590f6c32 100644 --- a/rom/exec/allocmem.c +++ b/rom/exec/allocmem.c @@ -86,7 +86,7 @@ D(if (SysBase->DebugAROSBase)) D(bug("Call AllocMem (%d, %08x)\n", byteSize, requirements)); - /* Zero bytes requested? May return everything ;-). */ + /* 0-sized allocation results in returning NULL (API guarantee) */ if(!byteSize) return NULL; diff --git a/rom/exec/allocpooled.c b/rom/exec/allocpooled.c index f58607eb95..0dd97a6d94 100644 --- a/rom/exec/allocpooled.c +++ b/rom/exec/allocpooled.c @@ -71,6 +71,10 @@ struct MemHeaderExt *mhe = (struct MemHeaderExt *)poolHeader; + /* 0-sized allocation results in returning NULL (API guarantee) */ + if(!memSize) + return NULL; + if (IsManagedMem(mhe)) { ULONG attributes = (ULONG)(IPTR)mhe->mhe_MemHeader.mh_First; diff --git a/rom/exec/allocvec.c b/rom/exec/allocvec.c index a26ac31843..dc799bf8b2 100644 --- a/rom/exec/allocvec.c +++ b/rom/exec/allocvec.c @@ -53,6 +53,10 @@ UBYTE *ret; + /* 0-sized allocation results in returning NULL (API guarantee) */ + if(!byteSize) + return NULL; + /* Add room for stored size. */ byteSize+=AROS_ALIGN(sizeof(IPTR)); diff --git a/rom/exec/allocvecpooled.c b/rom/exec/allocvecpooled.c index 079651aa2d..d2623cf73b 100644 --- a/rom/exec/allocvecpooled.c +++ b/rom/exec/allocvecpooled.c @@ -52,7 +52,11 @@ AROS_LIBFUNC_INIT struct MemHeaderExt *mhe = (struct MemHeaderExt *)poolHeader; - + + /* 0-sized allocation results in returning NULL (API guarantee) */ + if(!memSize) + return NULL; + if (IsManagedMem(mhe)) { ULONG attributes = (ULONG)(IPTR)mhe->mhe_MemHeader.mh_First; diff --git a/rom/exec/freemem.c b/rom/exec/freemem.c index 7dfaf5583a..638dec126e 100644 --- a/rom/exec/freemem.c +++ b/rom/exec/freemem.c @@ -64,7 +64,7 @@ D(bug("Call FreeMem (%08lx, %ld)\n", memoryBlock, byteSize)); - /* If there is no memory free nothing */ + /* If there is nothing to free do nothing. */ if(!byteSize || !memoryBlock) ReturnVoid ("FreeMem"); diff --git a/rom/exec/freepooled.c b/rom/exec/freepooled.c index 9d92e3c6bd..c2dd992f13 100644 --- a/rom/exec/freepooled.c +++ b/rom/exec/freepooled.c @@ -57,6 +57,10 @@ struct MemHeaderExt *mhe = (struct MemHeaderExt *)poolHeader; + /* If there is nothing to free do nothing. */ + if(!memSize || !memory) + return; + if (IsManagedMem(mhe)) { if (mhe->mhe_Free) diff --git a/rom/exec/freevec.c b/rom/exec/freevec.c index 8f02b1ab48..7f8f35aa8f 100644 --- a/rom/exec/freevec.c +++ b/rom/exec/freevec.c @@ -46,11 +46,12 @@ { AROS_LIBFUNC_INIT - /* If there's nothing to free do nothing. */ - if (memoryBlock != NULL) - { - memoryBlock -= AROS_ALIGN(sizeof(IPTR)); - FreeMem(memoryBlock, *((IPTR *)memoryBlock)); - } + /* If there is nothing to free do nothing. */ + if(!memoryBlock) + return; + + memoryBlock -= AROS_ALIGN(sizeof(IPTR)); + FreeMem(memoryBlock, *((IPTR *)memoryBlock)); + AROS_LIBFUNC_EXIT } /* FreeVec */ diff --git a/rom/exec/freevecpooled.c b/rom/exec/freevecpooled.c index 48133eba89..845692fa85 100644 --- a/rom/exec/freevecpooled.c +++ b/rom/exec/freevecpooled.c @@ -53,6 +53,10 @@ struct MemHeaderExt *mhe = (struct MemHeaderExt *)poolHeader; + /* If there is nothing to free do nothing. */ + if(!memory) + return; + if (IsManagedMem(mhe)) { if (mhe->mhe_FreeVec) diff --git a/test/exec/allocxxx.c b/test/exec/allocxxx.c new file mode 100644 index 0000000000..32c8951c92 --- /dev/null +++ b/test/exec/allocxxx.c @@ -0,0 +1,54 @@ +#include + +#include +#include +#include "test.h" + +APTR pool = NULL; +APTR poolclear = NULL; + +#define ALLOCTEST(cmd) \ + mem = cmd; \ + TEST((mem == NULL)) \ + +#define FREETEST(cmd) \ + cmd; \ + TEST((TRUE)) \ + +int main(int argc, char **argv) +{ + APTR mem = NULL; + pool = CreatePool(MEMF_ANY, 16384, 8192); + poolclear = CreatePool(MEMF_ANY|MEMF_CLEAR, 16384, 8192); + + /* Behavior validated with OS3.x, OS4.x and MorphOS */ + + ALLOCTEST(AllocMem(0, MEMF_ANY)) + ALLOCTEST(AllocMem(0, MEMF_ANY | MEMF_CLEAR)) + FREETEST(FreeMem(NULL, 0)) + + + ALLOCTEST(AllocVec(0, MEMF_ANY)) + ALLOCTEST(AllocVec(0, MEMF_ANY | MEMF_CLEAR)) + FREETEST(FreeVec(NULL)) + + + ALLOCTEST(AllocPooled(pool, 0)) + ALLOCTEST(AllocPooled(poolclear, 0)) + FREETEST(FreePooled(pool, NULL, 0)) + + + ALLOCTEST(AllocVecPooled(pool, 0)) + ALLOCTEST(AllocVecPooled(poolclear, 0)) + FREETEST(FreeVecPooled(pool, NULL)) + + cleanup(); + + return 0; +} + +void cleanup() +{ + DeletePool(pool); + DeletePool(poolclear); +} diff --git a/test/exec/mmakefile.src b/test/exec/mmakefile.src index eb70ad34b4..d896e8f122 100644 --- a/test/exec/mmakefile.src +++ b/test/exec/mmakefile.src @@ -7,6 +7,7 @@ include $(TOP)/config/make.cfg FILES := \ alert \ allocmem \ + allocxxx \ avltest \ childstatus \ childwait \ diff --git a/test/exec/test.h b/test/exec/test.h new file mode 100644 index 0000000000..7139d5d182 --- /dev/null +++ b/test/exec/test.h @@ -0,0 +1,29 @@ +/* Prototypes for mandatory functions */ +void cleanup( void ); + +/* Return values */ +#define OK 0 /* All tests succeded */ +#define FAIL 5 /* Some of the tests failed */ + +/* Testing macro */ +#define TEST(x) \ + if(!(x)) \ + { \ + printf( "Test FAILED in %s, line %d.\n", __FILE__, __LINE__ ); \ + cleanup(); \ + return FAIL; \ + } \ + else \ + { \ + printf( "Test passed in %s, line %d.\n", __FILE__, __LINE__ ); \ + } + +/* Only output when not passing */ +#define TESTFALSE(x) \ + if(!(x)) \ + { \ + printf( "Test FAILED in %s, line %d.\n", __FILE__, __LINE__ ); \ + cleanup(); \ + return FAIL; \ + } + -- 2.11.4.GIT