Message-ID: <3EEAFF3E.DB9719A7@yahoo.com> Date: Sat, 14 Jun 2003 06:55:58 -0400 From: CBFalconer Organization: Ched Research X-Mailer: Mozilla 4.75 [en] (Win98; U) X-Accept-Language: en MIME-Version: 1.0 To: djgpp-workers AT delorie DOT com Subject: Re: Integer Overflow References: <3EEA9A4B DOT 7B15E2A AT yahoo DOT com> <4098-Sat14Jun2003113806+0300-eliz AT elta DOT co DOT il> Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Reply-To: djgpp-workers AT delorie DOT com Eli Zaretskii wrote: > > > Date: Fri, 13 Jun 2003 23:45:15 -0400 > > From: CBFalconer > > > > compiled with "gcc -O0 -ftrapv ttrap.c > > > > It traps integer overflow quite nicely, although I don't approve > > of the code generation (what happened to INTO). > > Please show the code or disassembly fragment that you refer to here. > I cannot quite understand what you don't like about the code. (It's > also possible that I have a different compiler version installed, so > please do tell what "gcc --version" prints on your machine.) It is gcc 3.2.1. The following is a collection of snips from the screen and objdump, pasted as quote to avoid linewraps: ------------- start -------------- > [1] c:\c\junk>a > 0 fa16a64 + c667a71 = 1c07e4d5 > 1 2fb23202 + 19894e95 = 493b8097 > 2 2d82148 + 6aeda1d3 = 6dc5c31b > 3 5bfbc6d3 + 4acec095 = Abort! > Exiting due to signal SIGABRT > Raised at eip=0000460e > eax=0008fc24 ebx=00000120 ecx=00000000 edx=00000000 esi=00000054 edi=0000fd60 > ebp=0008fcd0 esp=0008fc20 program=C:\C\JUNK\A.EXE > cs: sel=00a7 base=87c3e000 limit=0009ffff > ds: sel=00af base=87c3e000 limit=0009ffff > es: sel=00af base=87c3e000 limit=0009ffff > fs: sel=0087 base=0001a5f0 limit=0000ffff > gs: sel=00bf base=00000000 limit=0010ffff > ss: sel=00af base=87c3e000 limit=0009ffff > App stack: [0008fd60..0000fd60] Exceptn stack: [0000fcc0..0000dd80] > > Call frame traceback EIPs: > 0x00004534 __djgpp_traceback_exit+48 > 0x0000460e raise+90 > 0x000036ab abort+27 > 0x00002909 __addvsi3+41 > 0x000016e2 main+153, file c:/c/junk/ttrap.c, line 17 > 0x00002f88 __crt1_startup+176 > > > Clips from "objdump -dS a.exe" > fflush(stdout); > 16c4: 83 ec 0c sub $0xc,%esp > 16c7: 68 80 b9 00 00 push $0xb980 > 16cc: e8 cf 1e 00 00 call 35a0 <_fflush> > 16d1: 83 c4 10 add $0x10,%esp > c = a + b; > 16d4: 83 ec 08 sub $0x8,%esp > 16d7: ff 75 f8 pushl 0xfffffff8(%ebp) > 16da: ff 75 fc pushl 0xfffffffc(%ebp) > 16dd: e8 fe 11 00 00 call 28e0 <___addvsi3> > 16e2: 83 c4 10 add $0x10,%esp > 16e5: 89 45 f4 mov %eax,0xfffffff4(%ebp) > printf("%10x\n", c); > > 000028e0 <___addvsi3>: > 28e0: 55 push %ebp > 28e1: 89 e5 mov %esp,%ebp > 28e3: 50 push %eax > 28e4: 50 push %eax > 28e5: 8b 45 0c mov 0xc(%ebp),%eax > 28e8: 8b 4d 08 mov 0x8(%ebp),%ecx > 28eb: 85 c0 test %eax,%eax > 28ed: 8d 14 08 lea (%eax,%ecx,1),%edx > 28f0: 78 0e js 2900 <___addvsi3+0x20> > 28f2: 39 ca cmp %ecx,%edx > 28f4: 7c 0e jl 2904 <___addvsi3+0x24> > 28f6: 89 ec mov %ebp,%esp > 28f8: 89 d0 mov %edx,%eax > 28fa: 5d pop %ebp > 28fb: c3 ret > 28fc: 8d 74 26 00 lea 0x0(%esi,1),%esi > 2900: 39 ca cmp %ecx,%edx > 2902: 7e f2 jle 28f6 <___addvsi3+0x16> > 2904: e8 87 0d 00 00 call 3690 <_abort> > 2909: 90 nop > 290a: 90 nop > 290b: 90 nop > 290c: 90 nop > 290d: 90 nop > 290e: 90 nop > 290f: 90 nop > > 00003690 <_abort>: > 3690: 55 push %ebp > 3691: 89 e5 mov %esp,%ebp > 3693: 6a 08 push $0x8 > 3695: 68 a0 b9 00 00 push $0xb9a0 > 369a: 6a 02 push $0x2 > 369c: e8 6f 15 00 00 call 4c10 <__write> > 36a1: 68 20 01 00 00 push $0x120 > 36a6: e8 09 0f 00 00 call 45b4 <_raise> > 36ab: 6a 01 push $0x1 > 36ad: e8 a6 13 00 00 call 4a58 <__exit> > 36b2: 89 f6 mov %esi,%esi > ... -------------- end ----------- The code from addvsi3 comes from the library, not from me. The library failing is probably due to the gcc under which it was compiled. > > > However if you > > follow the code via "objdump -dS a.exe | less" you will find that > > addition is performed by a subroutine, that eventually calls abort > > (all with some number of prepended _s). The call to abort has NO > > following code. > > > > This works fine if the purpose is to abort. But why can't the > > user set up a signal handler to trap SIGABRT, handle it, and > > return? If so the program will be left in total limbo. > > As far as I could see, those functions where there's no code after the > call to `abort' are from libgcc.a. They are part of the GCC > distribution and are maintained by the GCC developers. So any > problems with that code (and I agree that not having at least RET > after the call to `abort' might be wrong) should be reported to the > GCC forum. > > Having said that, I wonder what would be the Right Thing to do if the > call to `abort' returns in this case. Also, if a program wants to be > trapped on overflows, it should probably not have a SIGABRT handler > that returns. That is, it's a documentation issue at most: tell in > the GCC manual that programs compiled with -ftrapv had better not > define such a handler. Well, for example the program could have the handler set a volatile flag and return. Then the user code might be something like: c = a + b; if (flag) { /* do something to get the user to re-enter */ /* and set up something to go around again */ } it is all very hairy, but clearly impossible if the handler can't return. > > > The same problem appears in other places after raising a signal, > > and that is also a gcc problem. > > What places are those? > > > The code generation is obviously a gcc problem, but the overflow > > handling is a library problem, and thus peculiar to DJGPP. > > Please elaborate: how is overflow handling a library problem? See above. It is not just overflows, it is raising signals in general. Compile something with "raise(SIGABRT);" and look at the code generated. It is possible the problem is limited to use of SIGABRT, and that the prevention of return is deliberate. I haven't looked at other signals. However raise is documented as returning a value. However integer overflow should not cause an abort willy-nilly. The application should be able to catch them. There is a mention (in signal.h) of "256 software interrupts + 32 exceptions = 288". I have no idea what exceptions are in this context, but it makes me suspicious that addvsi3 is doing something wrong, and that this is symptomatic. At any rate I now know that I can use -ftrapv in development and catch silly errors. A better usage would be to generate INTO instructions with minimal impact on execution, provided INTO can be hooked for individual processes. And this goes deep into DOS/Wxx flavors, so there may be good reasons for the handling. I hope I am being reasonably clear. -- Chuck F (cbfalconer AT yahoo DOT com) (cbfalconer AT worldnet DOT att DOT net) Available for consulting/temporary embedded and systems. USE worldnet address!