[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Bug-tar] free(valloc()): invalid pointer
From: |
Paul Eggert |
Subject: |
Re: [Bug-tar] free(valloc()): invalid pointer |
Date: |
Mon, 02 Aug 2004 22:02:12 -0700 |
User-agent: |
Gnus/5.1006 (Gnus v5.10.6) Emacs/21.3 (gnu/linux) |
Justin Pryzby <address@hidden> writes:
> Please see Debian bug #248897 at [1] and its sibling at [2]. tar uses
> valloc() to get aligned memory, and later free()s it. However, the
> pointer returned by glibc valloc() is not necessarily free()able.
Thanks for reporting this. I see that the underlying problem is a bug
in Debian glibc (Debian bug 262782, which you just filed). It's
clearly a bug, as the glibc manual says:
With the GNU library, you can use `free' to free the blocks that
`memalign', `posix_memalign', and `valloc' return.
<http://www.gnu.org/software/libc/manual/html_node/Aligned-Memory-Blocks.html#Aligned%20Memory%20Blocks>
That being said, tar should work around the Debian bug, as similar
problems apparently occur on a few other platforms. I installed the
following patch into the tar CVS main branch.
2004-08-02 Paul Eggert <address@hidden>
* bootstrap (gnulib_modules): Add getpagesize.
* configure.ac (valloc): Remove check; valloc no longer used.
* lib/.cvsignore: Add getpagesize.h.
* m4/.cvsignore: Add getpagesize.m4.
* src/buffer.c (record_buffer): New var.
(open_archive): Don't use valloc; on older or buggy hosts, you can't
free the result. Use page_aligned_alloc instead.
* src/compare.c (diff_init): Likewise.
* src/buffer.c (open_archive): Record the pointer to be freed
into record_buffer.
(close_archive): Free record_buffer.
* src/common.h (page_aligned_alloc): New decl.
* src/misc.c (quote_n, quote): Remove these redundant functions.
(ptr_align): New function, from coreutils/src/system.h.
(page_aligned_alloc): New function.
* src/system.h (valloc): Remove.
Index: bootstrap
===================================================================
RCS file: /cvsroot/tar/tar/bootstrap,v
retrieving revision 1.16
diff -p -u -r1.16 bootstrap
--- bootstrap 19 May 2004 10:32:52 -0000 1.16
+++ bootstrap 3 Aug 2004 04:41:05 -0000
@@ -150,6 +150,7 @@ full-write
getdate
getline
getopt
+getpagesize
gettext
gettime
hash
Index: configure.ac
===================================================================
RCS file: /cvsroot/tar/tar/configure.ac,v
retrieving revision 1.43
diff -p -u -r1.43 configure.ac
--- configure.ac 16 May 2004 20:47:07 -0000 1.43
+++ configure.ac 3 Aug 2004 04:41:05 -0000
@@ -132,7 +132,6 @@ LIBS=$tar_save_LIBS
AC_CHECK_FUNCS(fsync lstat mkfifo readlink strerror symlink setlocale utimes)
AC_CHECK_DECLS([getgrgid],,, [#include <grp.h>])
AC_CHECK_DECLS([getpwuid],,, [#include <pwd.h>])
-AC_CHECK_DECLS([valloc])
AC_CHECK_DECLS([time],,, [#include <time.h>])
# Set LIB_SETSOCKOPT to -lnsl -lsocket if necessary.
Index: lib/.cvsignore
===================================================================
RCS file: /cvsroot/tar/tar/lib/.cvsignore,v
retrieving revision 1.9
diff -p -u -r1.9 .cvsignore
--- lib/.cvsignore 10 Jul 2004 06:51:38 -0000 1.9
+++ lib/.cvsignore 3 Aug 2004 04:41:05 -0000
@@ -40,6 +40,7 @@ getopt.c
getopt.h
getopt1.c
getopt_int.h
+getpagesize.h
gettext.h
gettime.c
gettimeofday.c
Index: m4/.cvsignore
===================================================================
RCS file: /cvsroot/tar/tar/m4/.cvsignore,v
retrieving revision 1.10
diff -p -u -r1.10 .cvsignore
--- m4/.cvsignore 16 May 2004 20:55:18 -0000 1.10
+++ m4/.cvsignore 3 Aug 2004 04:41:05 -0000
@@ -21,6 +21,7 @@ getdate.m4
getline.m4
getndelim2.m4
getopt.m4
+getpagesize.m4
gettext.m4
gettime.m4
gettimeofday.m4
Index: src/buffer.c
===================================================================
RCS file: /cvsroot/tar/tar/src/buffer.c,v
retrieving revision 1.68
diff -p -u -r1.68 buffer.c
--- src/buffer.c 19 May 2004 14:25:27 -0000 1.68
+++ src/buffer.c 3 Aug 2004 04:41:05 -0000
@@ -40,6 +40,7 @@
static tarlong prev_written; /* bytes written on previous volumes */
static tarlong bytes_written; /* bytes written on this volume */
+static void *record_buffer; /* allocated memory */
/* FIXME: The following variables should ideally be static to this
module. However, this cannot be done yet. The cleanup continues! */
@@ -270,17 +271,12 @@ open_archive (enum access_mode wanted_ac
save_name = 0;
real_s_name = 0;
+ record_start =
+ page_aligned_alloc (&record_buffer,
+ (record_size
+ + (multi_volume_option ? 2 * BLOCKSIZE : 0)));
if (multi_volume_option)
- {
- record_start = valloc (record_size + (2 * BLOCKSIZE));
- if (record_start)
- record_start += 2;
- }
- else
- record_start = valloc (record_size);
- if (!record_start)
- FATAL_ERROR ((0, 0, _("Cannot allocate memory for blocking factor %d"),
- blocking_factor));
+ record_start += 2;
current_block = record_start;
record_end = record_start + blocking_factor;
@@ -946,7 +942,7 @@ close_archive (void)
free (save_name);
if (real_s_name)
free (real_s_name);
- free (multi_volume_option ? record_start - 2 : record_start);
+ free (record_buffer);
}
/* Called to initialize the global volume number. */
Index: src/common.h
===================================================================
RCS file: /cvsroot/tar/tar/src/common.h,v
retrieving revision 1.37
diff -p -u -r1.37 common.h
--- src/common.h 29 Jun 2004 10:10:26 -0000 1.37
+++ src/common.h 3 Aug 2004 04:41:06 -0000
@@ -586,6 +586,8 @@ void write_fatal_details (char const *,
pid_t xfork (void);
void xpipe (int[2]);
+void *page_aligned_alloc (void **, size_t);
+
/* Module names.c. */
extern struct name *gnu_list_name;
Index: src/compare.c
===================================================================
RCS file: /cvsroot/tar/tar/src/compare.c,v
retrieving revision 1.20
diff -p -u -r1.20 compare.c
--- src/compare.c 5 Apr 2004 02:29:18 -0000 1.20
+++ src/compare.c 3 Aug 2004 04:41:06 -0000
@@ -54,9 +54,8 @@ static char *diff_buffer;
void
diff_init (void)
{
- diff_buffer = valloc (record_size);
- if (!diff_buffer)
- xalloc_die ();
+ void *ptr;
+ diff_buffer = page_aligned_alloc (&ptr, record_size);
}
/* Sigh about something that differs by writing a MESSAGE to stdlis,
Index: src/misc.c
===================================================================
RCS file: /cvsroot/tar/tar/src/misc.c,v
retrieving revision 1.18
diff -p -u -r1.18 misc.c
--- src/misc.c 16 May 2004 20:50:56 -0000 1.18
+++ src/misc.c 3 Aug 2004 04:41:06 -0000
@@ -916,18 +916,29 @@ xpipe (int fd[2])
call_arg_fatal ("pipe", _("interprocess channel"));
}
-/* Return an unambiguous printable representation, allocated in slot N,
- for NAME, suitable for diagnostics. */
-char const *
-quote_n (int n, char const *name)
+/* Return PTR, aligned upward to the next multiple of ALIGNMENT.
+ ALIGNMENT must be nonzero. The caller must arrange for ((char *)
+ PTR) through ((char *) PTR + ALIGNMENT - 1) to be addressable
+ locations. */
+
+static inline void *
+ptr_align (void *ptr, size_t alignment)
{
- return quotearg_n_style (n, locale_quoting_style, name);
+ char *p0 = ptr;
+ char *p1 = p0 + alignment - 1;
+ return p1 - (size_t) p1 % alignment;
}
-/* Return an unambiguous printable representation of NAME, suitable
- for diagnostics. */
-char const *
-quote (char const *name)
+/* Return the address of a page-aligned buffer of at least SIZE bytes.
+ The caller should free *PTR when done with the buffer. */
+
+void *
+page_aligned_alloc (void **ptr, size_t size)
{
- return quote_n (0, name);
+ size_t alignment = getpagesize ();
+ size_t size1 = size + alignment;
+ if (size1 < size)
+ xalloc_die ();
+ *ptr = xmalloc (size1);
+ return ptr_align (*ptr, alignment);
}
Index: src/system.h
===================================================================
RCS file: /cvsroot/tar/tar/src/system.h,v
retrieving revision 1.19
diff -p -u -r1.19 system.h
--- src/system.h 16 May 2004 20:56:05 -0000 1.19
+++ src/system.h 3 Aug 2004 04:41:06 -0000
@@ -502,10 +502,6 @@ time_t time ();
#define _(msgid) gettext (msgid)
#define N_(msgid) msgid
-#if ! defined valloc && ! HAVE_DECL_VALLOC
-# define valloc(size) malloc (size)
-#endif
-
#if MSDOS
# include <process.h>
# define SET_BINARY_MODE(arc) setmode(arc, O_BINARY)