On 15/04/2012 20:50, Marvin Humphrey wrote:
Here's the provisional API for the new feature Err#trap:
/** Run<code>routine</code> within the host's exception handling
* environment, catching and returning any errors that occur.
*
* If an unrecognized host exception is trapped, it will be wrapped in an
* Err so that it can be handled by Clownfish code.
*
* @return an Err, or NULL if no exception occurs.
*/
public inert incremented nullable Err*
trap(cfish_Err_attempt_t routine, void *context);
Here's sample usage, where we use Err#trap to implement a "Safe_Do_Stuff"
method which traps "MyError" exceptions which might be thrown by "Do_Stuff":
struct do_stuff_context {
Foo *foo;
int64_t number;
const char *string;
int64_t result;
};
static void
S_run_do_stuff(void *context) {
struct do_stuff_context *args = (struct do_stuff_context*)context;
args.result = Foo_Do_Stuff(args->foo, args->number, args->string);
}
int64_t
Foo_safe_do_stuff(Foo *self, int64_t number, const char *string) {
struct do_stuff_context context;
context.foo = self;
context.number = number;
context.string = string;
Err *error = Err_trap(S_run_do_stuff,&context);
if (error) {
if (Err_Is_A(error, MYERROR)) {
Err_set_error(error);
return -1;
}
else {
RETHROW(error);
}
}
else {
return args.result;
}
}
Thoughts?
I don't think there's an easier way to do this in C, so +1.
The one thing I'm not settled about in the provisional implementation is the
behavior of the XS helper function Err#run, which is where we extract an
arbitrary C function pointer out of a scalar and run it blindly.
void
run(routine_sv, context_sv)
SV *routine_sv;
SV *context_sv;
PPCODE:
IV routine_iv = SvIV(routine_sv);
IV context_iv = SvIV(context_sv);
cfish_Err_attempt_t routine = INT2PTR(cfish_Err_attempt_t, routine_iv);
void *context = INT2PTR(void*, context_iv);
routine(context);
I'm concerned that there might be an attack vector where a malicious user gets
shellcode into a scalar somewhere (easy), and then gets the first argument to
Err#run to point at it (hard, I think). I haven't yet figured out how to
complete that attack, though. Anybody see a problem?
Hmm, it seems that we can't we use the XCPT_* macros. But I think you
can create an anonymous XSUB by passing NULL as name argument to newXS
and using the return value.
Nick