[Bug libobjc/22492] New: [PATCH] Abort after @finally: libobjc passing exception value instead of exception.
creep at desk dot pl
gcc-bugzilla@gcc.gnu.org
Thu Jul 14 18:08:00 GMT 2005
gcc41 -v
Using built-in specs.
Target: i386-portbld-freebsd5.4
Configured with: ./..//gcc-4.1-20050709/configure --disable-rpath --disable-nls
--with-system-zlib --with-libiconv-prefix=/usr/local --program-suffix=41
--libdir=/usr/local/lib/gcc/i386-portbld-freebsd5.4/4.1.0
--with-gxx-include-dir=/usr/local/lib/gcc/i386-portbld-freebsd5.4/4.1.0/include/c++/
--disable-shared --disable-libgcj --prefix=/usr/local i386-portbld-freebsd5.4
Thread model: posix
gcc version 4.1.0 20050709 (experimental)
Problem:
Objective-C programs with @finally block will abort() in _Unwind_Resume when
leaving the @finally block while exception is thrown.
Example program:
------------------------------------------------
#include <objc/Object.h>
int
thrower_try_body()
{
printf("Thrower try body\n");
return (0);
}
int
finally_body()
{
printf("Finally body\n");
return (0);
}
int
thrower()
{
@try
{
thrower_try_body();
@throw [Object new];
}
@finally
{
finally_body();
} // <----- program aborts here.
return 0;
}
int
main(int ac, char *av[])
{
@try
{
thrower();
}
@catch (id exc)
{
printf("Got exception of class %s\n", [[exc class] name]);
[exc free];
}
}
-----------------------------------------------
The @finally block in thrower function code generated from exception throwing :
8048f94: e8 0c 62 00 00 call 804f1a5 <objc_exception_throw>
(exception value in %eax saved to stack)
8048f99: 89 45 f4 mov %eax,0xfffffff4(%ebp)
8048f9c: 8b 5d f4 mov 0xfffffff4(%ebp),%ebx
8048f9f: e8 89 ff ff ff call 8048f2d <finally_body>
8048fa4: 89 5d f4 mov %ebx,0xfffffff4(%ebp)
8048fa7: 83 ec 0c sub $0xc,%esp
8048faa: ff 75 f4 pushl 0xfffffff4(%ebp)
(exception value restored and passed to _Unwind_Resume)
8048fad: e8 12 ca 00 00 call 80559c4 <_Unwind_Resume>
_Unwind_Resume (gcc/unwind.inc) requires (struct _Unwind_Exception *) or derived
(struct ObjcException*) argument, so passing exception value ((struct Object*)
in this case) causes it to abort() (due to bad exception class).
Proposed solution:
The __gnu_objc_personality_v0 (and propably *_sj0 also) in exception.c should
return the exception structure in case saw_cleanup is set. Otherwise, it should
return the exception value (As it is now), but _Unwind_DeleteException the
exception calloc'ed in objc_exception_throw if personality is not in
_UA_SEARCH_PHASE.
Patch fixing __gnu_objc_personality_v0:
----------------------------------------
--- libobjc.old/exception.c Wed Jul 13 15:59:46 2005
+++ libobjc/exception.c Wed Jul 13 16:59:45 2005
@@ -165,7 +165,8 @@
const unsigned char *p;
_Unwind_Ptr landing_pad, ip;
int handler_switch_value;
- int saw_cleanup, saw_handler;
+ int saw_cleanup=0, saw_handler;
+ id return_object;
/* Interface version check. */
if (version != 1)
@@ -334,8 +335,14 @@
}
install_context:
+ if (saw_cleanup==0)
+ {
+ return_object = xh->value;
+ if (!(actions & _UA_SEARCH_PHASE))
+ _Unwind_DeleteException(&xh->base);
+ }
_Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
- __builtin_extend_pointer (xh->value));
+ __builtin_extend_pointer (saw_cleanup ? xh : return_object));
_Unwind_SetGR (context, __builtin_eh_return_data_regno (1),
handler_switch_value);
_Unwind_SetIP (context, landing_pad);
--------8<-------------8<--------------------
Patched version works and does not leak exception structures nor accesses free'd
memory (tested with valgrind).
--
Summary: [PATCH] Abort after @finally: libobjc passing exception
value instead of exception.
Product: gcc
Version: 4.1.0
Status: UNCONFIRMED
Severity: normal
Priority: P2
Component: libobjc
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: creep at desk dot pl
CC: gcc-bugs at gcc dot gnu dot org
GCC build triplet: 4.1.0 20050709
GCC host triplet: i386-portbld-freebsd5.4
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=22492
More information about the Gcc-bugs
mailing list