From owner-freebsd-bugs Wed Oct 22 14:00:09 1997 Return-Path: Received: (from root@localhost) by hub.freebsd.org (8.8.7/8.8.7) id OAA27418 for bugs-outgoing; Wed, 22 Oct 1997 14:00:09 -0700 (PDT) (envelope-from owner-freebsd-bugs) Received: (from gnats@localhost) by hub.freebsd.org (8.8.7/8.8.7) id OAA27386; Wed, 22 Oct 1997 14:00:02 -0700 (PDT) (envelope-from gnats) Resent-Date: Wed, 22 Oct 1997 14:00:02 -0700 (PDT) Resent-Message-Id: <199710222100.OAA27386@hub.freebsd.org> Resent-From: gnats (GNATS Management) Resent-To: freebsd-bugs Resent-Reply-To: FreeBSD-gnats@FreeBSD.ORG, tadhunt@bell-labs.com Received: (from nobody@localhost) by hub.freebsd.org (8.8.7/8.8.7) id NAA27302; Wed, 22 Oct 1997 13:59:25 -0700 (PDT) (envelope-from nobody) Message-Id: <199710222059.NAA27302@hub.freebsd.org> Date: Wed, 22 Oct 1997 13:59:25 -0700 (PDT) From: tadhunt@bell-labs.com To: freebsd-gnats-submit@FreeBSD.ORG X-Send-Pr-Version: www-1.0 Subject: i386/4826: libc_r, buggy setjmp implementation (rookie error) Sender: owner-freebsd-bugs@FreeBSD.ORG X-Loop: FreeBSD.org Precedence: bulk >Number: 4826 >Category: i386 >Synopsis: libc_r, buggy setjmp implementation (rookie error) >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Wed Oct 22 14:00:01 PDT 1997 >Last-Modified: >Originator: Tad Hunt >Organization: Lucent Technologies, Bell Labs >Release: 2.2.5-971018-BETA >Environment: doesn't matter. It's not specific to a particular version of FreeBSD, it's incorrect implementation of a library... >Description: I was looking at the libc_r implementation of setjmp (lib/libc_r/uthread/uthread_setjmp.c) from (FreeBSD-2.2.5-101897) from lib/libc_r/uthread/uthread_setjmp.c: int setjmp(jmp_buf env) { return (_thread_sys_setjmp(env)); } where _thread_sys_setjmp is implemented in lib/libc/i386/gen/setjmp.S as something like the following: #ifdef _THREAD_SAFE ENTRY(_thread_sys_setjmp) #else ENTRY(setjmp) #endif [... essentially the same implementation for both cases, except for some signal stuff] In the case of threaded programs calling setjmp() (instead of calling _thread_sys_setjmp()) the wrong environment gets saved in the jmp_buf. When longjmp does it's work, it returns into setjmp() (instead of returning into the caller of setjmp(). Essentially the following is happening: jmp_buf foo; main() { bar(); longjmp(foo, 1); } bar() { setjmp(foo); } -Tad >How-To-Repeat: % gcc -static foo.c -lc_r % ./a.out Memory Fault (core dumped) % foo.c: #include #include jmp_buf j; void main(void) { if(setjmp(j)) { printf("setjmp returned the second time\n"); exit(1); } longjmp(j, 69); } >Fix: diff lib/libc/i386/gen/setjmp.orig.S lib/libc/i386/gen/setjmp.S 59,30d58 < #else < ENTRY(setjmp) 61a60 > ENTRY(setjmp) >Audit-Trail: >Unformatted: