delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2024/10/01/16:57:29

X-Authentication-Warning: delorie.com: mail set sender to djgpp-bounces using -f
DKIM-Filter: OpenDKIM Filter v2.11.0 delorie.com 491KvJwk3672892
Authentication-Results: delorie.com;
dkim=pass (2048-bit key, unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=gOQhZnvp
X-Recipient: djgpp AT delorie DOT com
X-Original-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=gmail.com; s=20230601; t=1727816237; x=1728421037; darn=delorie.com;
h=content-transfer-encoding:subject:from:to:content-language
:user-agent:mime-version:date:message-id:from:to:cc:subject:date
:message-id:reply-to;
bh=NmWJQH3LjIplvxVKHILi5vJV7Sh5+rfeHH0xTPA2604=;
b=gOQhZnvpyAlnbYGBeS4PmE+oCGyboovZ7OXQgjFKzBz/6BT2L0778ya3vB+gfbTOEu
OgUnHOLrFm5O9epnibJ3Vj/1X44KOYipuDR3OqeDuhXWncxXkKjx4da+/i7uPPJgl3Ke
zW3QU5iroiwnyBnVQjZp6YHV3YCz6fLfr8GoAMfqBAEse9zt4MkSKvlwAgUrcn7VK9j5
l+DnbEK0DObQ3BcDcxSGVJck/Ayt+jzuZZ2swL2HyguQ190R+fNI84EdziANGuddYru2
mcuiCTba+FTM6JEBP3B4D0XtM5nfucF9GRnjvkVwRgjED5ZMEa66Fg4nftq3bP2bo2QO
BErQ==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=1e100.net; s=20230601; t=1727816237; x=1728421037;
h=content-transfer-encoding:subject:from:to:content-language
:user-agent:mime-version:date:message-id:x-gm-message-state:from:to
:cc:subject:date:message-id:reply-to;
bh=NmWJQH3LjIplvxVKHILi5vJV7Sh5+rfeHH0xTPA2604=;
b=hGJA7otM8GRnXs6fgYA/0XwXFbN7BC9pdeMO05ietOBhC2WKMBJRwBNbiKKqBlD3iv
TCTC0NHIBYWiw3K/vF7Tk7ZCJoZPqhzEhKctSA4J5fH853tmAAi/w8dOP0B1+s05MTX8
euEnnpiFH9c4lCrbTW53C4nK852EjsSgE9IKaAo7C80B80IP46Ehz9Zgs44aF6YkCWaT
+r4eRVs5wgAUlTDtfUtdFgBNOEdLRRhrAeqIUaiMhp76GiJzPJpeoXqaPY7LzBK+Bg/r
+OdLX6GlFH/H1dNjLl/GKIuUrdfemgpM6JAEQ7F6t84rkyZRXlA9wiPLJdEjP4i5XapE
7ptw==
X-Gm-Message-State: AOJu0Yxb0uZdwKydjFplciFxq3iyC1e89uJ0i1bRkAGRGvF2gsC7iV6y
eVJcei14vbhfptKTXDsPoZsYMn5SQqbv6RRleyHLzRkEX/BYOVuDJhjMfw==
X-Google-Smtp-Source: AGHT+IE7zbC+nz6JdWY6pq8l7e40XdyahFGMQfMzfwhuAFOSd31nMJlAt3CY5lF8eGSBBTSkRefXiQ==
X-Received: by 2002:a05:6402:34cf:b0:5c5:cf0b:b515 with SMTP id 4fb4d7f45d1cf-5c8b18deb86mr506994a12.1.1727816236626;
Tue, 01 Oct 2024 13:57:16 -0700 (PDT)
Message-ID: <7d97575b-24ac-4d55-be14-266ade57b992@gmail.com>
Date: Tue, 1 Oct 2024 22:57:15 +0200
MIME-Version: 1.0
User-Agent: Mozilla Thunderbird
To: djgpp AT delorie DOT com
From: "J.W. Jagersma (jwjagersma AT gmail DOT com) [via djgpp AT delorie DOT com]" <djgpp AT delorie DOT com>
Subject: malloc clobbers sbrk'd memory
Reply-To: djgpp AT delorie DOT com

I believe I found a bug where malloc sporadically writes past the end
of a memory chunk.

I ran into this while working on mcount, which allocates the histogram
and call graph via sbrk.  When my test program was invoked with some
specific number of arguments, the first histogram entry was clobbered,
which in gprof appeared as if the program had spent a lot of time in
'start'.  Turns out: the clobber value is the same as the special 'NONE'
pointer used in nmalloc.c.

What I believe is happening: the minimum chunk size created by
__nmalloc_split is DATAOFFSET (which is sizeof(memblock)-4; does *not*
include prevfree).  But when the high half is then passed to
mv2freelist, it writes prevfree=NONE, which is now past the end of the
chunk.

Solution is probably to define MINSAVE as (ALIGN + sizeof (memblock)),
regardless of SAVEMEMORY tricks.  It might be worth adding another 16
bytes or so, since minimum-size chunks are useless and only add clutter
to the freelist.

See test case below.  Compile with -O0 and invoke with some number of
arguments.  On my machine the bug triggers with 21 single-char args,
like so:

C:\>test.exe x x x x x x x x x x x x x x x x x x x x x

But the exact number may be dependent on environment size or other
factors.

---
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

int main ()
{
  free (malloc (100000));
  int *p = (int *)sbrk (sizeof (int));
  *p = 0;

  for (unsigned i = 0; i != 100000; ++i)
  {
    void *q = malloc (1);

    if (*p != 0)
    {
      printf ("BAD: *p=%i after %u mallocs!\n", *p, i + 1);
      return 1;
    }

    if (q > (void *)p)
    {
      printf ("passed p after %u mallocs\n", i + 1);
      break;
    }
  }

  printf ("OK\n");
  return 0;
}

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019