Fix nasty use after free bug revealed by last munmap fix.
Unexport split_segment; it isn't needed elsewhere.
(Something still wrong with munmap.)
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2143 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/vg_include.h b/coregrind/vg_include.h
index 5878826..0ce9b13 100644
--- a/coregrind/vg_include.h
+++ b/coregrind/vg_include.h
@@ -1580,7 +1580,6 @@
extern Segment *VG_(find_segment)(Addr a);
extern Segment *VG_(next_segment)(Segment *);
-extern Segment *VG_(split_segment)(Addr a);
extern Bool VG_(seg_contains)(const Segment *s, Addr ptr, UInt size);
extern Bool VG_(seg_overlaps)(const Segment *s, Addr ptr, UInt size);
diff --git a/coregrind/vg_memory.c b/coregrind/vg_memory.c
index 3a50975..c8b42ba 100644
--- a/coregrind/vg_memory.c
+++ b/coregrind/vg_memory.c
@@ -142,6 +142,9 @@
ns->offset += delta;
ns->len -= delta;
+ if (s->filename != NULL)
+ ns->filename = VG_(arena_strdup)(VG_AR_CORE, s->filename);
+
if (ns->symtab != NULL)
VG_(symtab_incref)(ns->symtab);
@@ -156,17 +159,19 @@
{
Segment *s;
Segment *next;
- static const Bool debug = False || mem_debug;
- Addr end = addr+len;
+ static const Bool debug = True || mem_debug;
+ Addr end;
if (len == 0)
return;
+ len = PGROUNDUP(len);
+ vg_assert(addr == PGROUNDDN(addr));
+
if (debug)
VG_(printf)("unmap_range(%p, %d)\n", addr, len);
- len = PGROUNDUP(addr+len)-PGROUNDDN(addr);
- addr = PGROUNDDN(addr);
+ end = addr+len;
/* Everything must be page-aligned */
vg_assert((addr & (VKI_BYTES_PER_PAGE-1)) == 0);
@@ -182,7 +187,7 @@
if (debug)
VG_(printf)("unmap: addr=%p-%p s=%p ->addr=%p-%p len=%d\n",
- addr, addr+len, s, s->addr, s->addr+s->len, s->len);
+ addr, end, s, s->addr, seg_end, s->len);
if (!VG_(seg_overlaps)(s, addr, len)) {
if (debug)
@@ -217,12 +222,14 @@
*/
Int delta = (addr+len) - s->addr;
+ if (debug)
+ VG_(printf)(" case 3: s->addr=%p s->len=%d delta=%d\n", s->addr, s->len, delta);
+
s->addr += delta;
s->offset += delta;
s->len -= delta;
- if (debug)
- VG_(printf)(" case 3: s->addr=%p s->len=%d delta=%d\n", s->addr, s->len, delta);
+ vg_assert(s->len != 0);
} else if (addr > s->addr && end < seg_end) {
/* [addr, addr+len) is contained within a single segment
-> split segment into 3, delete middle portion
@@ -245,8 +252,8 @@
}
}
-/* If possible, merge segment with its neighbours - some segments,
- including s, may be destroyed in the process */
+/* Return true if two segments are adjacent and mergable (s1 is
+ assumed to have a lower ->addr than s2) */
static inline Bool neighbours(Segment *s1, Segment *s2)
{
if (s1->addr+s1->len != s2->addr)
@@ -273,8 +280,8 @@
return True;
}
-/* Merge segments in the address range if they're adjacent and
- compatible */
+/* If possible, merge segment with its neighbours - some segments,
+ including s, may be destroyed in the process */
static void merge_segments(Addr a, UInt len)
{
Segment *s;
diff --git a/coregrind/vg_symtab2.c b/coregrind/vg_symtab2.c
index bb0c847..a6e6bc9 100644
--- a/coregrind/vg_symtab2.c
+++ b/coregrind/vg_symtab2.c
@@ -1208,8 +1208,7 @@
si->start = seg->addr;
si->size = seg->len;
si->foffset = seg->offset;
- si->filename = VG_(arena_malloc)(VG_AR_SYMTAB, 1 + VG_(strlen)(seg->filename));
- VG_(strcpy)(si->filename, seg->filename);
+ si->filename = VG_(arena_strdup)(VG_AR_SYMTAB, seg->filename);
si->ref = 1;