diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2007-06-30 20:38:16 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2007-06-30 20:38:16 +0000 |
commit | 555eade3913955a67cc4b3a7bd62938426c3d985 (patch) | |
tree | ff37fc30fc48ad5f699fd915a19f2ba76dbd8cee | |
parent | 29c566d4a5deaace772a17c179e409e59e2df609 (diff) | |
download | px4-nuttx-555eade3913955a67cc4b3a7bd62938426c3d985.tar.gz px4-nuttx-555eade3913955a67cc4b3a7bd62938426c3d985.tar.bz2 px4-nuttx-555eade3913955a67cc4b3a7bd62938426c3d985.zip |
Fix error in realloc when memory is extended downward
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@295 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r-- | nuttx/ChangeLog | 2 | ||||
-rw-r--r-- | nuttx/Documentation/NuttX.html | 2 | ||||
-rw-r--r-- | nuttx/mm/mm_realloc.c | 76 |
3 files changed, 44 insertions, 36 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index 7a6e935f0..adf20a906 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -190,5 +190,7 @@ on thread/task exit. * Add environment variables APIs: environ, getenv, putenv, clearenv, setenv, unsetenv + * Correct an error in realloc() when the block is extended "down" in memory. + In this case, the old memory contents need to be copied to the new location. * Started m68322 diff --git a/nuttx/Documentation/NuttX.html b/nuttx/Documentation/NuttX.html index 0aa964dc9..e19cf3d0d 100644 --- a/nuttx/Documentation/NuttX.html +++ b/nuttx/Documentation/NuttX.html @@ -627,6 +627,8 @@ Other memory: unsetenv * Add environment variables APIs: environ, getenv, putenv, clearenv, setenv, unsetenv + * Correct an error in realloc() when the block is extended "down" in memory. + In this case, the old memory contents need to be copied to the new location. * Started m68322 </pre></ul> diff --git a/nuttx/mm/mm_realloc.c b/nuttx/mm/mm_realloc.c index 52dd56bb7..e7d07d65b 100644 --- a/nuttx/mm/mm_realloc.c +++ b/nuttx/mm/mm_realloc.c @@ -81,6 +81,7 @@ FAR void *realloc(FAR void *oldmem, size_t size) size_t oldsize; size_t prevsize = 0; size_t nextsize = 0; + FAR void *newmem; /* If oldmem is NULL, then realloc is equivalent to malloc */ @@ -261,64 +262,67 @@ FAR void *realloc(FAR void *oldmem, size_t size) if (takenext) { - FAR struct mm_freenode_s *newnode; - FAR struct mm_allocnode_s *andbeyond; + FAR struct mm_freenode_s *newnode; + FAR struct mm_allocnode_s *andbeyond; - /* Get the chunk following the next node (which could be the tail chunk) */ + /* Get the chunk following the next node (which could be the tail chunk) */ - andbeyond = (FAR struct mm_allocnode_s*)((char*)next + nextsize); + andbeyond = (FAR struct mm_allocnode_s*)((char*)next + nextsize); - /* Remove the next node. There must be a predecessor, - * but there may not be a successor node. - */ + /* Remove the next node. There must be a predecessor, + * but there may not be a successor node. + */ - DEBUGASSERT(next->blink); - next->blink->flink = next->flink; - if (next->flink) - { - next->flink->blink = next->blink; - } + DEBUGASSERT(next->blink); + next->blink->flink = next->flink; + if (next->flink) + { + next->flink->blink = next->blink; + } - /* Extend the node into the previous next chunk */ + /* Extend the node into the next chunk */ - oldnode->size = oldsize + takenext; - newnode = (FAR struct mm_freenode_s *)((char*)oldnode + oldnode->size); + oldnode->size = oldsize + takenext; + newnode = (FAR struct mm_freenode_s *)((char*)oldnode + oldnode->size); - /* Did we consume the entire preceding chunk? */ + /* Did we consume the entire preceding chunk? */ - if (takenext < nextsize) - { - /* No, take what we need from the next chunk and return it - * to the free nodelist. - */ + if (takenext < nextsize) + { + /* No, take what we need from the next chunk and return it + * to the free nodelist. + */ - newnode->size = nextsize - takenext; - newnode->preceding = oldnode->size; - andbeyond->preceding = newnode->size | (andbeyond->preceding & MM_ALLOC_BIT); + newnode->size = nextsize - takenext; + newnode->preceding = oldnode->size; + andbeyond->preceding = newnode->size | (andbeyond->preceding & MM_ALLOC_BIT); - /* Add the new free node to the nodelist (with the new size) */ + /* Add the new free node to the nodelist (with the new size) */ - mm_addfreechunk(newnode); - } - else - { - /* Yes, just update some pointers. */ + mm_addfreechunk(newnode); + } + else + { + /* Yes, just update some pointers. */ - andbeyond->preceding = oldnode->size | (andbeyond->preceding & MM_ALLOC_BIT); - } + andbeyond->preceding = oldnode->size | (andbeyond->preceding & MM_ALLOC_BIT); + } } + /* Now we have to move the user contents 'down' in memory. memcpy should + * should be save for this. + */ + newmem = (FAR void*)((FAR char*)oldnode + SIZEOF_MM_ALLOCNODE); + memcpy(newmem, oldmem, oldsize - SIZEOF_MM_ALLOCNODE); mm_givesemaphore(); - return (FAR void*)((FAR char*)oldnode + SIZEOF_MM_ALLOCNODE); + return newmem; } /* The current chunk cannot be extended. Just allocate a new chunk and copy */ else { - FAR void *newmem; - /* Allocate a new block. On failure, realloc must return NULL but * leave the original memory in place. */ |