summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-06-30 20:38:16 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-06-30 20:38:16 +0000
commit555eade3913955a67cc4b3a7bd62938426c3d985 (patch)
treeff37fc30fc48ad5f699fd915a19f2ba76dbd8cee
parent29c566d4a5deaace772a17c179e409e59e2df609 (diff)
downloadnuttx-555eade3913955a67cc4b3a7bd62938426c3d985.tar.gz
nuttx-555eade3913955a67cc4b3a7bd62938426c3d985.tar.bz2
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/ChangeLog2
-rw-r--r--nuttx/Documentation/NuttX.html2
-rw-r--r--nuttx/mm/mm_realloc.c76
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.
*/