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

Reply via email to