tests/exec
tests/inspect
tests/pump
+tests/reading_long_line
tests/redirect
+Wed Apr 24 07:48:26 BST 2013 Colin Watson <cjwatson@debian.org>
+
+ * Version: 1.2.3.
+ * lib/Makefile.am (libpipeline_la_LDFLAGS): Bump -version-info to
+ 3:3:2.
+
+Wed Apr 24 07:44:38 BST 2013 Colin Watson <cjwatson@debian.org>
+
+ * lib/pipeline.c (pipeline_wait_all): Free active_pipelines if it is
+ entirely empty.
+
+Wed Apr 24 07:27:44 BST 2013 Peter Schiffer <pschiffe@redhat.com>
+
+ * lib/pipeline.c (pipecmd_new_argstr): Fix memory leak when the
+ first word of argstr is "exec".
+ * tests/argstr.c (test_argstr_exec): Free cmd at end.
+ * tests/basic.c (test_basic_wait_all): Free statuses at end.
+ (test_basic_clearenv): Free p and p2 at end.
+ * tests/exec.c (test_exec_process, test_exec_function): Free cmd at
+ end of loop.
+ * tests/redirect.c (test_redirect_files): Free p and template at
+ end.
+
+Tue Apr 23 07:52:40 BST 2013 Colin Watson <cjwatson@debian.org>
+
+ * lib/pipeline.c (pipecmd_exec): Flush stdio before starting a
+ sequence.
+ * NEWS: Document this.
+
+Tue Apr 23 07:50:45 BST 2013 Peter Schiffer <pschiffe@redhat.com>
+ Colin Watson <cjwatson@debian.org>
+
+ Don't read uninitialised memory when testing for the end of long
+ lines (Fedora bug #876108).
+
+ * lib/pipeline.c (get_line): Fix incorrect memchr bounds.
+ * tests/Makefile.am (TESTS): Add reading_long_line.
+ (reading_long_line_SOURCES, reading_long_line_LDADD): Add.
+ * tests/reading_long_line.c: New file.
+ * .bzrignore: Add tests/reading_long_line.
+ * NEWS: Document this.
+
+Mon Jan 21 11:42:09 GMT 2013 Colin Watson <cjwatson@debian.org>
+
+ * configure.ac (AC_HEADER_SYS_WAIT): Remove; superseded by Gnulib.
+
+Mon Jan 21 11:26:15 GMT 2013 Colin Watson <cjwatson@debian.org>
+
+ Upgrade to Libtool 2.4.2-1.2 (from Debian).
+
+Mon Dec 24 02:23:37 GMT 2012 Colin Watson <cjwatson@debian.org>
+
+ * lib/pipeline.c (pipeline_start): Remove redundant condition.
+
Mon Sep 17 22:54:12 BST 2012 Colin Watson <cjwatson@debian.org>
* Version: 1.2.2.
+libpipeline 1.2.3 (24 April 2013)
+=================================
+
+Don't read uninitialised memory when testing for the end of long lines (over
+4096 bytes).
+
+Flush stdio before starting a sequence.
+
libpipeline 1.2.2 (17 September 2012)
=====================================
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
-/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
+/* Define to 1 if you have the <sys/wait.h> header file. */
#undef HAVE_SYS_WAIT_H
/* Define to 1 if you have the `tsearch' function. */
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for libpipeline 1.2.2.
+# Generated by GNU Autoconf 2.69 for libpipeline 1.2.3.
#
# Report bugs to <cjwatson@debian.org>.
#
# Identity of this package.
PACKAGE_NAME='libpipeline'
PACKAGE_TARNAME='libpipeline'
-PACKAGE_VERSION='1.2.2'
-PACKAGE_STRING='libpipeline 1.2.2'
+PACKAGE_VERSION='1.2.3'
+PACKAGE_STRING='libpipeline 1.2.3'
PACKAGE_BUGREPORT='cjwatson@debian.org'
PACKAGE_URL=''
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures libpipeline 1.2.2 to adapt to many kinds of systems.
+\`configure' configures libpipeline 1.2.3 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of libpipeline 1.2.2:";;
+ short | recursive ) echo "Configuration of libpipeline 1.2.3:";;
esac
cat <<\_ACEOF
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-libpipeline configure 1.2.2
+libpipeline configure 1.2.3
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by libpipeline $as_me 1.2.2, which was
+It was created by libpipeline $as_me 1.2.3, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
# Define the identity of the package.
PACKAGE='libpipeline'
- VERSION='1.2.2'
+ VERSION='1.2.3'
cat >>confdefs.h <<_ACEOF
;;
*)
lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
- if test -n "$lt_cv_sys_max_cmd_len"; then
+ if test -n "$lt_cv_sys_max_cmd_len" && \
+ test undefined != "$lt_cv_sys_max_cmd_len"; then
lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
else
LD="${LD-ld} -m elf_i386_fbsd"
;;
x86_64-*linux*)
- LD="${LD-ld} -m elf_i386"
+ case `/usr/bin/file conftest.o` in
+ *x86-64*)
+ LD="${LD-ld} -m elf32_x86_64"
+ ;;
+ *)
+ LD="${LD-ld} -m elf_i386"
+ ;;
+ esac
;;
ppc64-*linux*|powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sys/wait.h that is POSIX.1 compatible" >&5
-$as_echo_n "checking for sys/wait.h that is POSIX.1 compatible... " >&6; }
-if ${ac_cv_header_sys_wait_h+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <sys/types.h>
-#include <sys/wait.h>
-#ifndef WEXITSTATUS
-# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8)
-#endif
-#ifndef WIFEXITED
-# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
-#endif
-
-int
-main ()
-{
- int s;
- wait (&s);
- s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_header_sys_wait_h=yes
-else
- ac_cv_header_sys_wait_h=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_sys_wait_h" >&5
-$as_echo "$ac_cv_header_sys_wait_h" >&6; }
-if test $ac_cv_header_sys_wait_h = yes; then
-
-$as_echo "#define HAVE_SYS_WAIT_H 1" >>confdefs.h
-
-fi
-
for ac_header in fcntl.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "fcntl.h" "ac_cv_header_fcntl_h" "$ac_includes_default"
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by libpipeline $as_me 1.2.2, which was
+This file was extended by libpipeline $as_me 1.2.3, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-libpipeline config.status 1.2.2
+libpipeline config.status 1.2.3
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
dnl Process this file with autoconf to produce a configure script.
-# Copyright (C) 2010 Colin Watson.
+# Copyright (C) 2010, 2011, 2012, 2013 Colin Watson.
#
# This file is part of libpipeline.
#
m4_pattern_forbid([^PIPELINE_])
# Initialise and check we're in the correct directory.
-AC_INIT([libpipeline], [1.2.2], [cjwatson@debian.org])
+AC_INIT([libpipeline], [1.2.3], [cjwatson@debian.org])
AC_CONFIG_AUX_DIR([tools])
AM_INIT_AUTOMAKE([1.10 -Wall -Werror foreign])
AM_MAINTAINER_MODE
# Check for various header files and associated libraries.
AC_ISC_POSIX
gl_INIT
-AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS([fcntl.h])
# Checks for structures and compiler characteristics.
LD="${LD-ld} -m elf_i386_fbsd"
;;
x86_64-*linux*)
- LD="${LD-ld} -m elf_i386"
+ case `/usr/bin/file conftest.o` in
+ *x86-64*)
+ LD="${LD-ld} -m elf32_x86_64"
+ ;;
+ *)
+ LD="${LD-ld} -m elf_i386"
+ ;;
+ esac
;;
ppc64-*linux*|powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
*)
lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
- if test -n "$lt_cv_sys_max_cmd_len"; then
+ if test -n "$lt_cv_sys_max_cmd_len" && \
+ test undefined != "$lt_cv_sys_max_cmd_len"; then
lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
else
libpipeline_la_LDFLAGS = \
-export-symbols-regex '^(pipecmd|pipeline)_' \
- -version-info 3:2:2
+ -version-info 3:3:2
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libpipeline.pc
libpipeline_la_LIBADD = ../gnulib/lib/libgnu.la $(LTLIBOBJS)
libpipeline_la_LDFLAGS = \
-export-symbols-regex '^(pipecmd|pipeline)_' \
- -version-info 3:2:2
+ -version-info 3:3:2
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libpipeline.pc
* work when being executed directly. To work around this,
* we just drop "exec" if it appears at the start of argstr.
*/
+ free (arg);
arg = argstr_get_word (&argstr);
if (!arg)
error (FATAL, 0,
struct pipecmd_sequence *cmds = &cmd->u.sequence;
struct sigaction sa;
+ /* Flush all pending output so that subprocesses
+ * don't inherit it.
+ */
+ fflush (NULL);
+
/* pipeline_start will have blocked SIGCHLD. We like
* it that way. Lose the parent's signal handler,
* though.
p->outfd = pdes[0];
output_read = pdes[0];
output_write = pdes[1];
- } else if (i == p->ncommands - 1) {
+ } else {
if (p->redirect_out == REDIRECT_FD)
output_write = p->want_out;
else if (p->redirect_out == REDIRECT_FILE_NAME) {
if (active_pipelines[i] == p)
active_pipelines[i] = NULL;
+ /* It isn't normally safe to compactify active_pipelines as we go,
+ * because it's used by a signal handler. However, if it's entirely
+ * empty, we can safely clean it up now. This prevents the table
+ * growing without bound, not to mention pacifying valgrind.
+ */
+ for (i = 0; i < n_active_pipelines; ++i)
+ if (active_pipelines[i])
+ break;
+ if (i == n_active_pipelines) {
+ n_active_pipelines = 0;
+ max_active_pipelines = 0;
+ free (active_pipelines);
+ active_pipelines = NULL;
+ }
+
if (statuses && n_statuses) {
*statuses = xnmalloc (p->ncommands, sizeof **statuses);
*n_statuses = p->ncommands;
if (!buffer || plen == 0)
return NULL;
- end = memchr (buffer + block * i, '\n', plen);
+ end = memchr (buffer + block * i, '\n', plen - block * i);
if (!end && plen < block * (i + 1))
/* end of file, no newline found */
end = buffer + plen - 1;
exec \
inspect \
pump \
- redirect
+ redirect \
+ reading_long_line
check_PROGRAMS = $(TESTS)
LIBS = ../gnulib/lib/libgnu.la $(LTLIBOBJS) $(top_builddir)/lib/libpipeline.la
redirect_SOURCES = redirect.c common.c common.h
redirect_LDADD = $(LIBS) @CHECK_LIBS@
+
+reading_long_line_SOURCES = reading_long_line.c common.c common.h
+reading_long_line_LDADD = $(LIBS) @CHECK_LIBS@
build_triplet = @build@
host_triplet = @host@
TESTS = basic$(EXEEXT) argstr$(EXEEXT) exec$(EXEEXT) inspect$(EXEEXT) \
- pump$(EXEEXT) redirect$(EXEEXT)
+ pump$(EXEEXT) redirect$(EXEEXT) reading_long_line$(EXEEXT)
check_PROGRAMS = $(am__EXEEXT_1)
subdir = tests
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am__EXEEXT_1 = basic$(EXEEXT) argstr$(EXEEXT) exec$(EXEEXT) \
- inspect$(EXEEXT) pump$(EXEEXT) redirect$(EXEEXT)
+ inspect$(EXEEXT) pump$(EXEEXT) redirect$(EXEEXT) \
+ reading_long_line$(EXEEXT)
am_argstr_OBJECTS = argstr.$(OBJEXT) common.$(OBJEXT)
argstr_OBJECTS = $(am_argstr_OBJECTS)
argstr_DEPENDENCIES = $(LIBS)
am_pump_OBJECTS = pump.$(OBJEXT) common.$(OBJEXT)
pump_OBJECTS = $(am_pump_OBJECTS)
pump_DEPENDENCIES = $(LIBS)
+am_reading_long_line_OBJECTS = reading_long_line.$(OBJEXT) \
+ common.$(OBJEXT)
+reading_long_line_OBJECTS = $(am_reading_long_line_OBJECTS)
+reading_long_line_DEPENDENCIES = $(LIBS)
am_redirect_OBJECTS = redirect.$(OBJEXT) common.$(OBJEXT)
redirect_OBJECTS = $(am_redirect_OBJECTS)
redirect_DEPENDENCIES = $(LIBS)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
SOURCES = $(argstr_SOURCES) $(basic_SOURCES) $(exec_SOURCES) \
- $(inspect_SOURCES) $(pump_SOURCES) $(redirect_SOURCES)
+ $(inspect_SOURCES) $(pump_SOURCES) \
+ $(reading_long_line_SOURCES) $(redirect_SOURCES)
DIST_SOURCES = $(argstr_SOURCES) $(basic_SOURCES) $(exec_SOURCES) \
- $(inspect_SOURCES) $(pump_SOURCES) $(redirect_SOURCES)
+ $(inspect_SOURCES) $(pump_SOURCES) \
+ $(reading_long_line_SOURCES) $(redirect_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
pump_LDADD = $(LIBS) @CHECK_LIBS@
redirect_SOURCES = redirect.c common.c common.h
redirect_LDADD = $(LIBS) @CHECK_LIBS@
+reading_long_line_SOURCES = reading_long_line.c common.c common.h
+reading_long_line_LDADD = $(LIBS) @CHECK_LIBS@
all: all-am
.SUFFIXES:
pump$(EXEEXT): $(pump_OBJECTS) $(pump_DEPENDENCIES) $(EXTRA_pump_DEPENDENCIES)
@rm -f pump$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(pump_OBJECTS) $(pump_LDADD) $(LIBS)
+reading_long_line$(EXEEXT): $(reading_long_line_OBJECTS) $(reading_long_line_DEPENDENCIES) $(EXTRA_reading_long_line_DEPENDENCIES)
+ @rm -f reading_long_line$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(reading_long_line_OBJECTS) $(reading_long_line_LDADD) $(LIBS)
redirect$(EXEEXT): $(redirect_OBJECTS) $(redirect_DEPENDENCIES) $(EXTRA_redirect_DEPENDENCIES)
@rm -f redirect$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(redirect_OBJECTS) $(redirect_LDADD) $(LIBS)
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exec.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inspect.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pump.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reading_long_line.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/redirect.Po@am__quote@
.c.o:
fail_unless (cmd->u.process.argc == 2);
fail_unless (!strcmp (cmd->u.process.argv[0], "foo"));
fail_unless (!strcmp (cmd->u.process.argv[1], "bar"));
+ pipecmd_free (cmd);
}
END_TEST
fail_unless (statuses[1] == 3 * 256);
fail_unless (statuses[2] == 0);
pipeline_free (p);
+ free (statuses);
}
END_TEST
"clearenv+setenv+dup returned second line '%s', expected 'bar\n'",
line2);
pipeline_wait (p2);
+ pipeline_free (p2);
+ pipeline_free (p);
}
END_TEST
fail_unless (WEXITSTATUS (status) == i);
else
fail_if (WEXITSTATUS (status) == 0);
+
+ pipecmd_free (cmd);
}
}
END_TEST
fail_unless (WIFEXITED (status));
fail_unless (WEXITSTATUS (status) == i);
+
+ pipecmd_free (cmd);
}
}
END_TEST
--- /dev/null
+/*
+ * Copyright (C) 2013 Peter Schiffer.
+ *
+ * This file is part of libpipeline.
+ *
+ * libpipeline is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * libpipeline is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with libpipeline; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA.
+ */
+
+/*
+ * Unit test for bug: https://bugzilla.redhat.com/show_bug.cgi?id=876108
+ */
+
+#include <string.h>
+#include <errno.h>
+#include "xvasprintf.h"
+
+#include "common.h"
+
+/* Must be 8194 or bigger */
+#define RANDOM_STR_LEN 9000
+
+START_TEST (test_reading_longline)
+{
+ /* Generate long random string */
+ static const char *alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz";
+ char random_string[RANDOM_STR_LEN] = "";
+ unsigned i;
+
+ for (i = 0; i < RANDOM_STR_LEN - 2; i++) {
+ random_string[i] = alphanum[rand () % (strlen (alphanum) - 1)];
+ }
+ random_string[RANDOM_STR_LEN - 1] = '\0';
+
+ /* Write the random string to file */
+ char *testfile = xasprintf ("%s/test", temp_dir);
+ FILE *tfd = fopen (testfile, "w");
+ if (!tfd) {
+ fail ("fopen failed: %s", strerror (errno));
+ return;
+ }
+ fprintf (tfd, "%s\n", random_string);
+ fclose (tfd);
+
+ char *expected_output = xasprintf ("%s\n", random_string);
+
+ pipeline *p;
+ const char *line;
+ char *read_result = NULL, *temp = NULL;
+
+ /* File must be read twice to reproduce the bug */
+ p = pipeline_new ();
+ pipeline_want_infile (p, testfile);
+ pipeline_want_out (p, -1);
+ pipeline_start (p);
+ while ((line = pipeline_readline (p)) != NULL){
+ if (read_result) {
+ temp = read_result;
+ read_result = xasprintf ("%s%s", read_result, line);
+ free (temp);
+ } else {
+ read_result = xasprintf ("%s", line);
+ }
+ }
+ pipeline_free (p);
+ fail_unless (!strcmp (read_result, expected_output),
+ "Returned string doesn't match the input.");
+
+ free (read_result);
+ read_result = NULL;
+
+ p = pipeline_new ();
+ pipeline_want_infile (p, testfile);
+ pipeline_want_out (p, -1);
+ pipeline_start (p);
+ while ((line = pipeline_readline (p)) != NULL){
+ if (read_result) {
+ temp = read_result;
+ read_result = xasprintf ("%s%s", read_result, line);
+ free (temp);
+ } else {
+ read_result = xasprintf ("%s", line);
+ }
+ }
+ pipeline_free (p);
+ fail_unless (!strcmp (read_result, expected_output),
+ "Returned string doesn't match the input.");
+
+ free (testfile);
+ free (expected_output);
+ free (read_result);
+}
+END_TEST
+
+Suite *reading_long_line_suite (void)
+{
+ Suite *s = suite_create ("Reading long line");
+
+ TEST_CASE_WITH_FIXTURE (s, reading, longline,
+ temp_dir_setup, temp_dir_teardown);
+
+ return s;
+}
+
+MAIN (reading_long_line)
fclose (fh);
unlink (template);
+
+ pipeline_free (p);
+ free (template);
}
END_TEST
# compiler: $LTCC
# compiler flags: $LTCFLAGS
# linker: $LD (gnu? $with_gnu_ld)
-# $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1.1
+# $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1.2
# automake: $automake_version
# autoconf: $autoconf_version
#
PROGRAM=libtool
PACKAGE=libtool
-VERSION="2.4.2 Debian-2.4.2-1.1"
+VERSION="2.4.2 Debian-2.4.2-1.2"
TIMESTAMP=""
package_revision=1.3337