I've worked on this, and I think I've found the problem.  In the
smalloc.c file, there is:

====
static struct memnode *find_mn(struct mempool *mp, unsigned char *ptr)
{
  struct memnode *mn;
  if (!POOL_USED(mp)) {
    smerror("SMALLOC: unused pool passed\n");
    return NULL;
  }
  for (mn = &mp->mn; mn->next; mn = mn->next) {
    if (mn->mem_area > ptr)
      return NULL;
    if (mn->mem_area == ptr) {
      return mn;
    }
  }
  return NULL;
}
====

You can see that the loop condition is "mn->next".  However, because
of how the loop is structured, when mn->next is null, mn still has
useful information that does not get processed. This is the case that
triggers the "free" problem, since the memory is not properly freed,
then it runs out of memory.

You can compare this to this other function, also in smalloc.c:

====
static struct memnode *smfind_free_area(struct mempool *mp, size_t size)
{
  struct memnode *mn;
  for (mn = &mp->mn; mn; mn = mn->next) {
    if (!mn->used && mn->size >= size)
      return mn;
  }
  return NULL;
}
====

I've been looking at the code and found no reason why the loop
condition of the first function (used in the smfree call) should leave
out the last item, while the loop condition of the second function
(used in the smalloc call) shouldn't.  I changed the condition to just
"mn", recompiled and tested and everything seems to be working fine.

I'm not completely sure of my findings, since there are no comments at
all in the code, so I fear there still might be a weird reason for
this difference, that I wasn't able to figure out.  I'd prefer dosemu
people to comment on this, but the project seems to be stalled (no
commits for months).

In any case, I'm attaching the patch.  And I have a patched version
available at:

http://www.marga.com.ar/~marga/debian/packages/dosemu/dosemu_1.4.0+svn.1828-2.1_i386.deb

If this patch is found to be correct, it would be nice to include the
fix in "proposed-updates" since for some usecases (i.e. using one
program that triggers the bug, and another one that _needs_ xms), this
bug renders dosemu unsable.

-- 
Besos,
Marga
--- dosemu-1.4.0+svn.1828/src/base/misc/smalloc.c       2009-02-24 
16:33:53.000000000 -0200
+++ dosemu-1.4.0+svn.1828_p/src/base/misc/smalloc.c     2009-02-25 
10:27:55.000000000 -0200
@@ -73,7 +73,7 @@
     smerror("SMALLOC: unused pool passed\n");
     return NULL;
   }
-  for (mn = &mp->mn; mn->next; mn = mn->next) {
+  for (mn = &mp->mn; mn; mn = mn->next) {
     if (mn->mem_area > ptr)
       return NULL;
     if (mn->mem_area == ptr) {

Reply via email to