Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!cs.utexas.edu!usc!zaphod.mps.ohio-state.edu!rpi!sci.ccny.cuny.edu!cucard!proexam!glen From: glen@proexam.UUCP (Glen Brydon) Newsgroups: comp.lang.perl Subject: Re: Bugs in perl 3.0 pl 8 -- return statement Summary: Larry are ya listening? Please play it safe! Save your registers. Keywords: registers setjmp(3) random behavior unsafe JMPCLOBBER Message-ID: <418@proexam.UUCP> Date: 4 Feb 90 08:09:14 GMT References: <4080004@hpausla.aso.hp.com> <4080005@hpausla.aso.hp.com> Reply-To: glen@proexam.UUCP (Glen Brydon) Organization: Professional Examination Service, NYC Lines: 146 In article <4080005@hpausla.aso.hp.com> brian@hpausla.aso.hp.com (Brian Coogan) writes: >Brian Coogan writes in comp.lang.perl: >> I've just been fighting with the return statement of perl 3.0 pl 8 and >> losing badly. There appear to be some bugs... > >I just recompiled cmd.c with JMPCLOBBER defined and the bug went away. >Thanks for your help (especially Paul Maisano who suggested the fix). >Serves me right for not watching the fixes going by more closely. > >thanks folks, >Brian. I haven't seen any reply from Larry Wall about this stuff. It concerned me when Anders Pilegaard posted his alarming article giving rather mysterious symptoms (non of which I experienced). As he wrote to me: >From cucard!daimi.dk!andersp Tue Jan 30 01:18:04 1990 >Date: Mon, 29 Jan 90 14:45:49 +0100 >From: Anders Pilegaard >Subject: Re: IMPORTANT: Mysterious errors in perl patch level 8, solved >. . . >I then began actually debugging perl and after some time discovered >that a free string struct had some wild references resulting in >attempts to dereference a NIL pointer. After some more debugging it >appeared that this wild value was put there while the string struct >was free'd, indicating stray pointers. Quite some hours later I found >the real culprit, setjmp/longjmp. Perl uses a local register variable > ============== >st to hold a stack. As this stack may be changed by various routines >(foremost eval) it is often reset to the value of a global variable. >This is not done around setjmp, and setjmp/longjmp does NOT guarantee > ================== >handling of register variables correctly (At least is says so in the >======================================== >manual page on our sun-3). . . . > >It is both subtle and yet so simple. Because of the nature of this >bug, virtually ANY variable may be clobbered. It may appear in any > ======================================= >script utilising longjmp's, and that includes not only subroutines, >but also last, next, redo, and goto. But the fix is quite simple. > >Actually it seems that Larry Wall has foreseen this. He has introduced > ============================ >an #ifdef JMPCLOBBER around the critical sections. This activates >four assignments around each setjmp and should take care of all >critical variables. The problem is that he only defined it for >cray's and ANSI compilers. And it seems that at least sun's and hp's >should also define this. And who knows how many other >architectures/operating systems are affected? > >The reason that I posted my article with such an alarming header is >that it is quite difficult to determine whether a system is affected > =================================================== >by this bug. On our systems the same script produced two very visible >reactions (core dump) and two actions I wouldn't have noticed had I >not been debugging that particular script --- at least it would have >been some time before I found out. On my system (SunOS version 4.0.3 running on 3/280 arch) the man page for setjmp(3) is quite informative (more so than 4.3 BSD): SETJMP(3) C LIBRARY FUNCTIONS SETJMP(3) NAME setjmp, longjmp, sigsetjmp, siglongjmp - non-local goto . . . . . DESCRIPTION . . . . . setjmp() saves its stack environment in env for later use by longjmp. A normal call to setjmp() returns zero. setjmp() also saves the register environment. If a longjmp() call ============================== . . . . . point data registers are restored to the values they had at the time that setjmp() was called. But, because the regis- ter storage class is only a hint to the C compiler, vari- =========== ables declared as register variables may not necessarily be assigned to machine registers, so their values are unpredictable after a longjmp. This is especially a problem for programmers trying to write machine-independent C rou- =================== tines. . . . . . EXAMPLE The following code fragment indicates the flow of control of the setjmp() and longjmp() combination: function declaration ... jmp_buf my_environment; ... if (setjmp(my_environment)) { /* register variables have unpredictable values ==================== code after the return from longjmp ... } else { /* do not modify register vars this is the return from setjmp ... } SEE ALSO cc(1V), sigsetmask(2), sigvec(2), ieee_flags(3M), signal(3), setjmp(3V) BUGS . . . . . >> On Sun-2 and Sun-3 systems setjmp() also saves the register << >> environment. Therefore, all data that are bound to regis- << >> ters are restored to the values they had at the time that << >> setjmp() was called. All memory-bound data have values as << >> of the time longjmp() was called. However, because the << >> register storage class is only a hint to the C compiler, << >> variables declared as register variables may not necessarily << >> be assigned to machine registers, so their values are << >> unpredictable after a longjmp. When using compiler options << >> that specify automatic register allocation (see cc(1V)), the << >> compiler will not attempt to assign variables to registers << >> in routines that call setjmp. << ===================================================================== It seems only too clear that my computer and its operating system should be treated like the cray and those with ANSI compilers. I will be interested in seeing how Larry deals with this problem in his upcoming bugfix (#9). Are there systems out there which guarantee both that the compiler will in fact put your variable in a register AND that all the registers will be restored as Larry has assumed most will? Needless to say I have applied a temporary fix and for me this fixed Brian Coogan's return problem (as it did for him). While the gray areas of the language seem to be more interesting to most people (including me), this stuff scares me to death. Setjmp(3) seems in fact to be one of those gray areas of UNIX. As I wrote to Anders Pilegaard, it surprises me the way this particular problem has been publcized (or not). It is especially confusing then Larry already anticipated it, but seemed not to realize the danger of his assumptions. I hope to see the official fix for this one.