printf %(fmt)T fails when the time given is very large in a 64-bit linux environment. Looping over the powers of two and feeding it to printf shows the error, which exits the shell with a SIGSEGV
The problem seems to be in builtins/printf.def, as indicated by the backtrace attached (gdb.txt). ------------------------------------------------------------------------------- I'm running the latest bash from the git repository: $ echo $BASH_VERSION 4.2.37(3)-release $ uname -a Linux claret 3.4.2-2-ARCH #1 SMP PREEMPT Mon Jun 11 22:27:17 CEST 2012 x86_64 GNU/Linux $ lsb_release -a LSB Version: n/a Distributor ID: archlinux Description: Arch Linux Release: rolling Codename: n/a ------------------------------------------------------------------------------- The following snippet reproduces the problem: for i in {56..63}; do printf '%s ' $i; bash -c 'printf %\(%s\)T\\n $((2**$1))' _ $i; done Sample run: $ for i in {56..63}; do > printf '%s ' $i; > bash -c 'printf %\(%s\)T\\n $((2**$1))' _ $i; > done 56 Segmentation fault 57 Segmentation fault 58 Segmentation fault 59 Segmentation fault 60 Segmentation fault 61 Segmentation fault 62 Segmentation fault 63 Segmentation fault ------------------------------------------------------------------------------- The simple fix is to check if ``tm == NULL``, and show an error message, or default to some specific value. A 32-bit machine seems to handle overflow as a zero. I guess defaulting to zero is one option. I'm not sure which one is the best approach. I'm attaching the diff generated by git. It just checks if tm is NULL, and defaults to zero, but it is only to demonstrate that the bug is there, the code isn't written correctly. -- Eduardo A. Bustamante López
The program being debugged has been started already. Start it from the beginning? (y or n) Starting program: /home/dualbus/local/bin/bash Program received signal SIGSEGV, Segmentation fault. 0x00007ffff7686450 in __strftime_internal () from /lib/libc.so.6 #0 0x00007ffff7686450 in __strftime_internal () from /lib/libc.so.6 #1 0x00007ffff76880d6 in strftime_l () from /lib/libc.so.6 #2 0x000000000047e1b4 in printf_builtin (list=0x72cc08) at ./printf.def:474 #3 0x000000000042fdbf in execute_builtin (builtin=builtin@entry=0x47d410 <printf_builtin>, flags=flags@entry=0, subshell=subshell@entry=0, words=<error reading variable: Unhandled dwarf expression opcode 0xfa>) at execute_cmd.c:4109 #4 0x0000000000431998 in execute_builtin_or_function (flags=0, fds_to_close=0x76e208, redirects=<optimized out>, var=0x0, builtin=0x47d410 <printf_builtin>, words=0x72c908) at execute_cmd.c:4534 #5 execute_simple_command (simple_command=<optimized out>, pipe_in=pipe_in@entry=-1, pipe_out=pipe_out@entry=-1, async=async@entry=0, fds_to_close=fds_to_close@entry=0x76e208) at execute_cmd.c:3944 #6 0x00000000004329cf in execute_command_internal (fds_to_close=0x76e208, pipe_out=-1, pipe_in=-1, asynchronous=0, command=0x76e148) at execute_cmd.c:735 #7 execute_command_internal (command=0x76e148, asynchronous=0, pipe_in=-1, pipe_out=-1, fds_to_close=0x76e208) at execute_cmd.c:522 #8 0x0000000000435a4e in execute_command (command=0x76e148) at execute_cmd.c:382 #9 0x000000000041e01d in reader_loop () at eval.c:152 #10 0x000000000041c5bd in main (argc=1, argv=0x7fffffffe258, env=0x7fffffffe268) at shell.c:749
diff --git a/builtins/printf.def b/builtins/printf.def index 71a7c00..94e5af5 100644 --- a/builtins/printf.def +++ b/builtins/printf.def @@ -471,6 +471,11 @@ printf_builtin (list) sv_tz ("TZ"); /* XXX -- just make sure */ #endif tm = localtime (&secs); + if (tm == NULL) + { + secs = 0; + tm = localtime (&secs); + } n = strftime (timebuf, sizeof (timebuf), timefmt, tm); free (timefmt); if (n == 0)