Richard Levitte - VMS Whacker <[EMAIL PROTECTED]>:

[...]
> The easiest way to avoid the conversions noted above is to have a
> union like this:
> 
>       union foo {
>               void *simple;
>               int (*fn)();
>       };
> 
> and use it internally.  You put whatever char * you want to convert to
> a functino pointer into simple and pull out the function pointer from
> fn, and vice versa.

You cannot convert things this way, that would be just as broken as
using casts.  What you can do, of course, is put pointers into the
appropriate union member ('simple' for data pointers, 'fn' for
function pointers), pass the union to some function, and, in this
function, take the same union member from the union passed as an
argument.  I thought you had done exactly that, but a second look in
the commitlog shows that you have not (and it would make SSL_[CTX_]ctrl
much more complicated, we'd have to change the prototype).

The clean way (and not just another "clever hack") would be

void SSL_CTX_set_tmp_rsa_callback(SSL_CTX *ctx,RSA *(*cb)(SSL *ssl,
                                                          int is_export,
                                                          int keylength))
    {
    RSA *(**cb_ptr)(SSL *, int, int) = &cb; /* cb_ptr is a data pointer,
                                             * not a function pointer */
    SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_RSA_CB,0,cb_ptr); /* no cast necessary as
                                                         * SSL_CTX_ctrl should
                                                         * have "void *" in the
                                                         * final argument */
    }

and in ssl3_ctrl (which is what SSL_CTX_ctrl ends up calling):

long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
        {
        [...]

        switch (cmd)
                {
        [...]

        case SSL_CTRL_SET_TMP_RSA_CB:
                {
                RSA *(**cb_ptr)(SSL *, int, int) = parg;
                
                s->cert->rsa_tmp_cb = *cb_ptr;
                }
                break;
        [...]
                }
        [...]
        }

Instead of directly passing function pointers in disguise, a pass
pointers to data objects containing the actual function pointers.

Note that I'm using temporary variables instead of single-line
commands involving casts because this way it can be hoped more
compilers will print warnings or error messages in case of a typo --
the explicit cast from a function pointer value to void * was enough
to bring gcc to silence, but without casts the compiler can see that
you don't really intend to do such evil things.
(SSL_CTX_ctrl, ssl3_ctrl et al. still have a char * argument where
they should have a void * -- it's certainly trivial to change that.)
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       [EMAIL PROTECTED]
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to