Merge r230433 from trunk:

* misc/apr_rmm.c (apr_rmm_realloc): Fix offset calculation.

* test/testrmm.c (test_rmm): Add test case.

Submitted by: Keith Kelleman <keith.kelleman oracle.com>



git-svn-id: https://svn.apache.org/repos/asf/apr/apr-util/branches/1.1.x@230442 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/CHANGES b/CHANGES
index 8f16c33..9fa543b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,8 @@
 Changes with APR-util 1.1.2
 
+  *) Fix apr_rmm_realloc() offset calculation bug.  [Keith Kelleman
+     <keith.kelleman oracle.com>]
+
   *) Fix handling of a premature EOF with the FILE bucket; a new bucket
      is not inserted for each attempt to read past EOF.  PR 34708.
      [Jeff Trawick, Joe Orton]
diff --git a/misc/apr_rmm.c b/misc/apr_rmm.c
index 0d4f020..439c87d 100644
--- a/misc/apr_rmm.c
+++ b/misc/apr_rmm.c
@@ -332,7 +332,7 @@
         return 0;
     }
 
-    blk = (rmm_block_t*)((char*)rmm->base + old);
+    blk = (rmm_block_t*)((char*)rmm->base + old - RMM_BLOCK_SIZE);
     oldsize = blk->size;
 
     memcpy(apr_rmm_addr_get(rmm, this),
diff --git a/test/testrmm.c b/test/testrmm.c
index 8203be1..b64b60b 100644
--- a/test/testrmm.c
+++ b/test/testrmm.c
@@ -190,12 +190,37 @@
         printf("FAILED\n");
         return rv;
     }
+
+    {
+        unsigned char *c = entity;
+
+        /* Fill in the region; the first half with zereos, which will
+         * likely catch the apr_rmm_realloc offset calculation bug by
+         * making it think the old region was zero length. */
+        for (i = 0; i < 100; i++) {
+            c[i] = (i < 50) ? 0 : i;
+        }
+    }
+
     /* now we can realloc off[1] and get many more bytes */
     off[0] = apr_rmm_realloc(rmm, entity, SHARED_SIZE - 100);
     if (off[0] == 0) {
         printf("FAILED\n");
         return APR_EINVAL;
     }
+
+    {
+        unsigned char *c = apr_rmm_addr_get(rmm, off[0]);
+
+        /* fill in the region */
+        for (i = 0; i < 100; i++) {
+            if (c[i] != (i < 50 ? 0 : i)) {
+                printf("FAILED at offset %d: %hx\n", i, c[i]);
+                return APR_EGENERAL;
+            }
+        }
+    }
+
     fprintf(stdout, "OK\n");
 
     printf("Destroying rmm segment...........................");