[Bug 276934] tcsh crash in rehist()

From: <bugzilla-noreply_at_freebsd.org>
Date: Fri, 09 Feb 2024 23:15:12 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=276934

            Bug ID: 276934
           Summary: tcsh crash in rehist()
           Product: Base System
           Version: 15.0-CURRENT
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Only Me
          Priority: ---
         Component: standards
          Assignee: standards@FreeBSD.org
          Reporter: joyul@juniper.net

Hi teams,

I encountered a crash in rehist() and below is its backtrace. In frame 3,
cleanup_sp is 0, which means it's already at the bottom of the cleanup_stack,
but last_var cannot be found.

It seems like in rehist(), it invokes setexit() without updating cleanup_mark.
If the program goes to error handling to reset the clean_stack[], it will clean
more than required, which should be handled by cleanup_until() when the program
jumps back to rehist().

I'm providing a patch below that might fix it. Feel free to apply it to the
tcsh git, FreeBSD baseline, or fix it using other solutions. We can downstream
it to our local and try it.

Thank you.

diff --git a/contrib/tcsh/sh.hist.c b/contrib/tcsh/sh.hist.c
index 14d862a3e7b..09f4814dbe3 100644
--- a/contrib/tcsh/sh.hist.c
+++ b/contrib/tcsh/sh.hist.c
@@ -1235,6 +1235,7 @@ rechist(Char *xfname, int ref)
     struct stat st;
     static Char *fname;
     static Char   *dumphist[] = {STRhistory, STRmhT, 0, 0};
+    size_t omark;

     if (fname == NULL && !ref)
        return;
@@ -1308,8 +1309,10 @@ rechist(Char *xfname, int ref)
 #endif
            }
            getexit(osetexit);
+           omark = cleanup_push_mark();
            if (setexit() == 0)
                loadhist(fname, 1);
+           cleanup_pop_mark(omark);
            resexit(osetexit);
        }
     }



(gdb) bt
#0  thr_kill () at thr_kill.S:4
#1  0x0000000001b7ee61 in __raise (s=s@entry=6)
    at
/.amd/svl-engdata5vs2/occamdev/build/freebsd/main/sandbox-main-202401181141/freebsd/main/20240118.171413__ci_fbsd_builder_main.c38f35a/src/lib/libc/gen/raise.c:50
#2  0x0000000001c1cca9 in abort ()
    at
/.amd/svl-engdata5vs2/occamdev/build/freebsd/main/sandbox-main-202401181141/freebsd/main/20240118.171413__ci_fbsd_builder_main.c38f35a/src/lib/libc/stdlib/abort.c:64
#3  0x000000000022148c in cleanup_until (last_var=0x1cc33c26ee80) at 
/src/contrib/tcsh/sh.err.c:470
#4  0x000000000022e68f in rechist (xfname=xfname@entry=0x0, ref=<optimized
out>) at  /src/contrib/tcsh/sh.hist.c:1327
#5  0x000000000021b2d0 in record () at  /src/contrib/tcsh/sh.c:2539
#6  0x000000000021b3e1 in phup () at  /src/contrib/tcsh/sh.c:1856
#7  0x0000000000261440 in handle_pending_signals () at 
/src/contrib/tcsh/tc.sig.c:67
#8  0x0000000000233c55 in xwrite (fildes=18, buf=0x28d170 <linbuf>, nbyte=11)
at  /src/contrib/tcsh/sh.misc.c:719
#9  0x00000000002352ff in flush () at  /src/contrib/tcsh/sh.print.c:256
#10 0x00000000002351d3 in xputchar (c=<optimized out>, c@entry=10) at 
/src/contrib/tcsh/sh.print.c:183
#11 0x0000000000235dcf in pprint (pp=0x1cc33c210a00, flag=160) at 
/src/contrib/tcsh/sh.proc.c:1178
#12 0x0000000000236385 in pjwait (pp=0x1cc33c210a00) at 
/src/contrib/tcsh/sh.proc.c:543
#13 0x00000000002361ab in pwait () at  /src/contrib/tcsh/sh.proc.c:473
#14 0x0000000000238c9d in execute (t=0x1cc33c25e090, wanttty=28987,
pipein=<optimized out>, pipeout=0x0, do_glob=do_glob@entry=1)
    at  /src/contrib/tcsh/sh.sem.c:623
#15 0x0000000000238983 in execute (t=t@entry=0x1cc33c25e060, wanttty=28987,
pipein=<optimized out>, pipein@entry=0x0, pipeout=pipeout@entry=0x0, 
    do_glob=do_glob@entry=1) at  /src/contrib/tcsh/sh.sem.c:724
#16 0x000000000021af01 in process (catch=<optimized out>) at 
/src/contrib/tcsh/sh.c:2166
#17 0x0000000000219d1e in main (argc=<optimized out>, argv=0x820710290) at 
/src/contrib/tcsh/sh.c:1431
(gdb) f 4
#4  0x000000000022e68f in rechist (xfname=xfname@entry=0x0, ref=<optimized
out>) at  /src/contrib/tcsh/sh.hist.c:1327


(gdb) f 3
#3  0x000000000022148c in cleanup_until (last_var=0x1cc33c26ee80) at
/src/contrib/tcsh/sh.err.c:470
470         abort();
(gdb) list
456         while (cleanup_sp != 0) {
457             struct cleanup_entry ce;
458     
459             cleanup_sp--;
460     
461             ce = cleanup_stack[cleanup_sp];
462             ce.fn(ce.var);
463     #ifdef CLEANUP_DEBUG
464             syslog(LOG_INFO,"[tcsh][cleanup_until] cleanup_sp %zu, file 
%s, line %zu, var %p\n", cleanup_sp, ce.file, ce.line, ce.var);
465     #endif
466             if (ce.var == last_var)
467                 return;
468         }
469         syslog(LOG_INFO, "abort in cleanup_until\n");
470         abort();
471     }
472     

(gdb) p cleanup_sp
$3 = 0

-- 
You are receiving this mail because:
You are the assignee for the bug.