Bug in patch bash42-018, leaves lastpipe_flag unitialized for platforms with out JOB_CONTROL.

2012-06-21 Thread John E. Malmberg

Hello Bash-bugs,

The patch bash42-018 to allow execute_cmd.c that is supposed to allow it 
to compile with out JOB_CONTROL defined has a bug in it.


It is leaving the lastpipe_flag uninitialized.  This is a problem 
because later in the module it is tested.


*** ../bash-4.2-patched/execute_cmd.c   2011-02-09 17:32:25.0 -0500
--- execute_cmd.c   2011-11-06 15:12:48.0 -0500
***
*** 2197,2200 
--- 2315,2319 
  cmd->flags |= CMD_IGNORE_RETURN;

+ #if defined (JOB_CONTROL)
lastpipe_flag = 0;
begin_unwind_frame ("lastpipe-exec");


The simple fix of moving the "#if defined (JOBCONTROL)" line below the 
"lastpipe_flag = 0;" may not be the ideal patch.


This is because JOB_CONTROL undefined, the entire if block lower below 
"QUIT;" is never executed, as lastpipe_flag is always 0.


Which means that it is kind of useless to have #if defined(JOB_CONTROL) 
blocks inside of it.  If this is the intended logic flow, then the 
entire "if (lastpipe_flag)" block should be conditionally compiled out.


Doing that and leaving the definition of the lastpipe_flag undefined as 
in the original patch will still result in a compiler diagnostic about 
an unused variable.


So that would need an #if defined (JOBCONTROL) needed around the 
declaration.


So what should be the correct patch?  Is there another bug hiding in this?

Regards,
-John
wb8tyw@qsl.network
Personal Opinion Only




Use of uninitialized values in mail checking

2012-06-21 Thread szymon . kalasz

Configuration Information:
Machine: i686
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='i686' 
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='i686-pc-linux-gnu' 
-DCONF_VENDOR='pc' -DLOCALEDIR='/usr/local/share/locale' 
-DPACKAGE='bash' -DSHELL -DHAVE_CONFIG_H   -I.  -I. -I./include -I./lib  
-g -O2
uname output: Linux harmony 3.2.4-1-ARCH #1 SMP PREEMPT Sat Feb 4 
11:21:15 UTC 2012 i686 Intel(R) Core(TM)2 Duo CPU T6400 @ 2.00GHz 
GenuineIntel GNU/Linux

Machine Type: i686-pc-linux-gnu

Bash Version: 4.2
Patch Level: 29
Release Status: release


I found that behavior of bash depends on uninitialized values in 
memory.
In function file_mod_date_changed (mailcheck.c), if mailstat returns a 
non-zero
value, we are checking condition finfo.st_size == 0, where 
finfo.st_size is

uninitialized. In those rare cases when finfo.st_size is zero and
mailfiles[i]->file_size > 0 we update mailfiles array with some random 
values

(while the file may even not exist).

Consider following scenario:

I have no specified mailbox path, so it defaults to /var/mail/szymon, 
which

does not exist.
Then I run bash:

./bash
[szymon@harmony bash]$ export MAILCHECK=0
[szymon@harmony bash]$ mkdir /var/mail/szymon
You have mail in /var/mail/szymon
[szymon@harmony bash]$ rm -r /var/mail/szymon
[szymon@harmony bash]$ mkdir /var/mail/szymon
[szymon@harmony bash]$
[szymon@harmony bash]$ rm -r /var/mail/szymon
[szymon@harmony bash]$
[szymon@harmony bash]$ mkdir /var/mail/szymon
[szymon@harmony bash]$
[szymon@harmony bash]$ exit

If I modify mailstat to put some specific values into struct stat *st
(st_size = 0 and st_mtime = 1) when stat() fails, I get the following:

./bash
[szymon@harmony bash]$ export MAILCHECK=0
[szymon@harmony bash]$ mkdir /var/mail/szymon
You have mail in /var/mail/szymon
[szymon@harmony bash]$ rm -r /var/mail/szymon
[szymon@harmony bash]$ mkdir /var/mail/szymon
You have mail in /var/mail/szymon
[szymon@harmony bash]$ rm -r /var/mail/szymon
[szymon@harmony bash]$ mkdir /var/mail/szymon
You have mail in /var/mail/szymon
[szymon@harmony bash]$ rm -r /var/mail/szymon
[szymon@harmony bash]$ mkdir /var/mail/szymon
You have mail in /var/mail/szymon
[szymon@harmony bash]$ rm -r /var/mail/szymon
[szymon@harmony bash]$ exit

So behavior of bash depends on these values. valgrind confirms that 
problem:

==13079== Conditional jump or move depends on uninitialised value(s)
==13079==at 0x809B922: check_mail (mailcheck.c:273)
==13079==by 0x806D0E3: yyparse (parse.y:2504)
==13079==by 0x80650AC: parse_command (eval.c:228)
==13079==by 0x806516D: read_command (eval.c:272)
==13079==by 0x80653A5: reader_loop (eval.c:137)
==13079==by 0x40DE482: (below main) (in /lib/libc-2.15.so)
==13079==

It seems to be a minor bug, however, still a bug.

For my convenience, I've added some debug printfs to mailcheck.c and 
mailstat.c.

You can see the output here:
1. uninitialized: http://szymon.kalasz.student.tcs.uj.edu.pl/b1.txt
2. st_size = 0, st_mtime = 1: 
http://szymon.kalasz.student.tcs.uj.edu.pl/b2.txt


Modified mailcheck.c and mailstat.c are available here:
http://szymon.kalasz.student.tcs.uj.edu.pl/bash/



Maybe it is better to UPDATE_MAIL_FILE only when (mail)stat returns 
zero?


diff --git a/mailcheck.c b/mailcheck.c
index bd95f0d..31aa970 100644
--- a/mailcheck.c
+++ b/mailcheck.c
@@ -263,14 +263,15 @@ file_mod_date_changed (i)
   time_t mtime;
   struct stat finfo;
   char *file;
+  int r;

   file = mailfiles[i]->name;
   mtime = mailfiles[i]->mod_time;

-  if ((mailstat (file, &finfo) == 0) && (finfo.st_size > 0))
+  if (((r = mailstat (file, &finfo)) == 0) && (finfo.st_size > 0))
 return (mtime < finfo.st_mtime);

-  if (finfo.st_size == 0 && mailfiles[i]->file_size > 0)
+  if (r == 0 && finfo.st_size == 0 && mailfiles[i]->file_size > 0)
 UPDATE_MAIL_FILE (i, finfo);

   return (0);



Re: Bug in patch bash42-018, leaves lastpipe_flag unitialized for platforms with out JOB_CONTROL.

2012-06-21 Thread Chet Ramey
On 6/21/12 8:42 AM, John E. Malmberg wrote:
> Hello Bash-bugs,
> 
> The patch bash42-018 to allow execute_cmd.c that is supposed to allow it to
> compile with out JOB_CONTROL defined has a bug in it.
> 
> It is leaving the lastpipe_flag uninitialized.  This is a problem because
> later in the module it is tested.
> 
> *** ../bash-4.2-patched/execute_cmd.c   2011-02-09 17:32:25.0 -0500
> --- execute_cmd.c   2011-11-06 15:12:48.0 -0500
> ***
> *** 2197,2200 
> --- 2315,2319 
>   cmd->flags |= CMD_IGNORE_RETURN;
> 
> + #if defined (JOB_CONTROL)
> lastpipe_flag = 0;
> begin_unwind_frame ("lastpipe-exec");
> 
> 
> The simple fix of moving the "#if defined (JOBCONTROL)" line below the
> "lastpipe_flag = 0;" may not be the ideal patch.

Maybe not, but it's enough to get started.  It just relies on the compiler
doing constant propagation and dead code removal to be as efficient as
using the preprocessor to not compile the code in at all.

I've attached the straightforward patch that does this.

The effect of the bug now is that some process may be waited for twice when
using a system without job control.  That's not a big deal.

I'm reluctant to make a more extensive change at this point because this
option makes sense for environments where there isn't job control.  In
fact, it makes more sense there because there isn't the process group issue
to have to worry about.  The code as it reads today only accommodates job
control systems, but that isn't the way it has to stay.

Chet
-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/


*** ../bash-4.2-patched/execute_cmd.c	2012-05-02 16:52:40.0 -0400
--- execute_cmd.c	2012-06-21 11:52:14.0 -0400
***
*** 2197,2202 
  cmd->flags |= CMD_IGNORE_RETURN;
  
- #if defined (JOB_CONTROL)
lastpipe_flag = 0;
begin_unwind_frame ("lastpipe-exec");
lstdin = -1;
--- 2318,2323 
  cmd->flags |= CMD_IGNORE_RETURN;
  
lastpipe_flag = 0;
+ #if defined (JOB_CONTROL)
begin_unwind_frame ("lastpipe-exec");
lstdin = -1;