This is a multi-part message in MIME format...

------------=_1188905019-46503-1
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: quoted-printable

Hopefully I've got the "subject" line right and this message will be
added to ticket #1546.

I came across the same problem when attempting to compile OpenSSL with
gcc 4.2.1 on Solarix 10 (x86). Briefly, the problem is because GCC 4.2
has tightened up the rules about what constitutes a compatible
function type. For anyone that's interested a more detailed
description of the problem follows. The attached patch applied to
0.9.8e fixes the problem.

The problem occurs because the "C" standard states that calling
functions through an incompatible prototype results in runtime
undefined behaviour. What GCC does in this case is replace the
function call with a call to abort "to encourage the user to fix the
program". This explains why the test suite then fails with
"instruction error"

The problem arises because of some of the function casts that OpenSSL
uses to get better type checking when calling more generic
functions. For example, there is the function ASN1_dup(), which
duplicates an object (I think). The function takes a pointer to the
object to duplicate (as a "char *") and pointers to generic "i2d" and
"d2i" functions and returns the duplicated object (as a "void *"). The
"C" types and prototypes are:

c> typedef int i2d_of_void(void *, unsigned char **);
c> typedef void *d2i_of_void(void **, const char **, long);
c>
c> void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, char *x);

This function is used in a number of places to create duplicates of
"DH", "DSA", "EC_KEY" and "OCSP_CERTID" objects. To use the function
to create a duplicate of a "DH" object (for example) the function must
be called with the appropriate "i2d" and "d2i function pointers and
supplied a pointer to a "DH" object (rather than a "char *"). That is,
the function needs to be called as if it had the following "C" types
and prototypes:

c> typedef int i2d_of_DH(const DH *, unsigned char **);
c> typedef DH *d2i_of_DH(DH **, const char **, long);
c>
c> DH *ASN1_dup_DH(i2d_of_DH *i2d, d2i_of_DH *d2i, const DH *x);

The OpenSSL code could just call the ASN1_dup() function directly,
casting the parameters to the correct types and casting the return
value to a "DH *" but that would be tedious and error prone (and
ugly). An alternative would be to use a macro something like:

c> #define DHparams_dup(x) (DH *)ASN1_dup((i2d_of_void *)i2d_DHparams, \
c> (d2i_of_void *)d2i_DHparams, (char *)x)

Where i2d_DHparams() and d2i_DHparams() are "i2d" and "d2i" functions
of the appropriate type.

That approach would work but has the drawback that the casting
circumvents some type checking that the compiler could perform. The
"DHparams_dup" macro should only ever be used passing a "const DH *" valu=
e
as the parameter "x". If it were erroneously used, passing an "EC_KEY *"
value as the parameter "x" then the compiler could give no warnings
as the "x" is cast to a "char *".

The approach that OpenSSL takes is to use some superficially complex
macros to cast the ASN1_dup() function to another function type that
take parameters of the right type and returns the right type. The
advantage with doing it this way is that the compiler can do some type
checking. For the example of duplicating "DH" objects the following
macros are used:

c> #define DHparams_dup(x) ASN1_dup_of_const(DH,i2d_DHparams,d2i_DHparams=
,x)
c>
c> #define ASN1_dup_of_const(type,i2d,d2i,x) \
C> ((type *(*)(I2D_OF_const(type),D2I_OF(type),type
*))openssl_fcast(ASN1_dup))(i2d,d2i,x)
c>
c> /* which uses the following macros/typedef */
c> #define I2D_OF_const(type) int (*)(const type *,unsigned char **)
c> #define D2I_OF(type) type *(*)(type **,const unsigned char **,long)
c> #define openssl_fcast(f) ((openssl_fptr)f)
c> typedef void (*openssl_fptr)(void);

What this has the effect of doing is to cast the ASN1_dup function to
be a function of the type:

c> DH *()(int (*)(const DH*, unsigned char **),
c> DH *(*)(DH **, const unsigned char**, long), const DH *);

and then calling the function with the i2d_DHparams() and
d2i_DHparams() functions and the supplied "x". This allows the
compiler to type check the "x" (and the i2d and d2i functions) and
give a warning or error if they're of the wrong type.

This is where the problem occurs. According to GCC 4.2 the type above
and the type of the ASN1_dup function are different enough that they
aren't considered compatible, so it inserts the abort.

The attached patch achieves the same effect as the function casts by
using some GCC specific features (the changes are inside preprocessor
conditionals for GCC v4.0 and above). The changes redefine the macros
with the function casts to be (GCC specific) "Statement Expression"
that define (GCC specific) "Nested functions" that take the required
parameter types. This maintains the type checking ability of the
original macros. For the example above (duplicating "DH" objects) the
DHparams_dup() macro remains the same but ASN1_dup_of_const() is
redefined as:

c> #define TYPEDEF_D2I_OF(type) typedef type *d2i_of_##type(type
**,const unsigned char **,long)
c> #define TYPEDEF_I2D_OF_const(type) typedef int
i2d_of_const_##type(const type *,unsigned char **)
c>
c> #if defined(__GNUC__) && __GNUC__ >=3D 4
c> # define ASN1_dup_of_const(type,i2d,d2i,x) ({ =
\
c> TYPEDEF_I2D_OF_const(type); =
\
c> TYPEDEF_D2I_OF(type); =
\
c> type * ASN1_dup_of_const_##type(i2d_of_const_##type*
_i2d,d2i_of_##type* _d2i,type *_x) { \
c> return ASN1_dup((i2d_of_void *)_i2d,(d2i_of_void *)_d2i,
(char *) _x); \
c> } =
\
c> ASN1_dup_of_const_##type(i2d, d2i, x); =
\
c> })
c> #else
c> # define ASN1_dup_of_const(type,i2d,d2i,x) \
c> ((type *(*)(I2D_OF_const(type),D2I_OF(type),type
*))openssl_fcast(ASN1_dup))(i2d,d2i,x)
c> #endif

Using GCC 4 or above the code fragment "dh_clnt =3D DHparams_dup(dh_srvr)=
" would
expand to:

c> dh_clnt =3D ({
c> typedef int i2d_of_const_DH(const DH*, unsigned char**);
c> typedef DH *d2i_of_DH(DH **, const unsigned char**, long);
c> DH *ASN1_dup_of_const_DH(i2d_of_const_DH *_i2d, d2i_of_DH* _d2i, DH =
*_x) {
c> return ASN1_dup((i2d_of_void *)_i2d, (d2i_of_void *)_d2i, (char *)=
_x);
c> }
c> ASN1_dup_of_const_DH(i2d_DHparams, d2i_DHparams, dh_srvr);
c> })

Which looks even worse than the original function cast. Oh well.

However, the way it works is quite straight forward. The "({"/"})" bit
is the GCC "statement expression" which turns the compound statement
(the bit inside the "{}" braces) into an expression. The value of the
statement expression is the value of the last thing in it, which in
this case is the result of calling ASN1_dup_of_const_DH(), a "DH *".

Within the statement expression the GCC "nested function" extension is
used to define the (nested) function ASN1_dup_of_const_DH() which is a
version of ASN1_dup() which takes parameters of the correct type (to
provide the type checking) and simply calls ASN1_dup (with the
appropriate casts). The typedefs are required to be able to refer to
the "i2d"/"d2i" parameters.

So, this redefinition of the ASN1_dup_of_const() macro provides all
the benefits of the original macro (the type-checking). It's
considerably longer than the original macro and appears as though it
might be less efficient with the nested function definition and
call. However, GCC is smart enough to optimise all that away. The
generated machine code (with GCC 4.1.3 on x86) is exactly the same as
with the original macro.

The attached patch applied to OpenSSL 0.9.8e compiles fine and passes
all tests on FreeBSD 6.1 using GCC 4.2.2 20070822 (prerelease).

Cheers,
Steve Nairn


------------=_1188905019-46503-1
Content-Type: text/plain; charset="ANSI_X3.4-1968"; name="patch.txt"
Content-Disposition: inline; filename="patch.txt"
Content-Transfer-Encoding: 7bit
RT-Attachment: 1546/17366/7170

diff -ru openssl-0.9.8e-orig/crypto/asn1/asn1.h openssl-0.9.8e/crypto/asn1/asn1.h
--- openssl-0.9.8e-orig/crypto/asn1/asn1.h Sun Feb 19 13:45:22 2006
+++ openssl-0.9.8e/crypto/asn1/asn1.h Fri Aug 31 16:13:15 2007
@@ -324,6 +324,7 @@

#define TYPEDEF_D2I_OF(type) typedef type *d2i_of_##type(type **,const unsigned char **,long)
#define TYPEDEF_I2D_OF(type) typedef int i2d_of_##type(type *,unsigned char **)
+#define TYPEDEF_I2D_OF_const(type) typedef int i2d_of_const_##type(const type *,unsigned char **)
#define TYPEDEF_D2I2D_OF(type) TYPEDEF_D2I_OF(type); TYPEDEF_I2D_OF(type)

TYPEDEF_D2I2D_OF(void);
@@ -902,23 +903,73 @@

/* Used to implement other functions */
void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, char *x);
+#if defined(__GNUC__) && __GNUC__ >= 4
+/* use a nested function to get the parameter checking */
+#define ASN1_dup_of(type,i2d,d2i,x) ({ \
+ TYPEDEF_D2I2D_OF(type); \
+ type * ASN1_dup_of_##type(i2d_of_##type *_i2d, d2i_of_##type* _d2i,type *_x) { \
+ return ASN1_dup((i2d_of_void *)_i2d,(d2i_of_void *)_d2i, (char *) _x); \
+ } \
+ ASN1_dup_of_##type(i2d, d2i, x); \
+ })
+#define ASN1_dup_of_const(type,i2d,d2i,x) ({ \
+ TYPEDEF_I2D_OF_const(type); \
+ TYPEDEF_D2I_OF(type); \
+ type * ASN1_dup_of_const_##type(i2d_of_const_##type* _i2d,d2i_of_##type* _d2i,type *_x) { \
+ return ASN1_dup((i2d_of_void *)_i2d,(d2i_of_void *)_d2i, (char *) _x); \
+ } \
+ ASN1_dup_of_const_##type(i2d, d2i, x); \
+ })
+#else
#define ASN1_dup_of(type,i2d,d2i,x) \
((type *(*)(I2D_OF(type),D2I_OF(type),type *))openssl_fcast(ASN1_dup))(i2d,d2i,x)
#define ASN1_dup_of_const(type,i2d,d2i,x) \
((type *(*)(I2D_OF_const(type),D2I_OF(type),type *))openssl_fcast(ASN1_dup))(i2d,d2i,x)
+#endif

void *ASN1_item_dup(const ASN1_ITEM *it, void *x);

#ifndef OPENSSL_NO_FP_API
void *ASN1_d2i_fp(void *(*xnew)(void), d2i_of_void *d2i, FILE *in, void **x);
-#define ASN1_d2i_fp_of(type,xnew,d2i,in,x) \
+#if defined(__GNUC__) && __GNUC__ >= 4
+# define ASN1_d2i_fp_of(type,xnew,d2i,in,x) \
+ ({ \
+ TYPEDEF_D2I_OF(type); \
+ type * ASN1_d2i_fp_of_##type(type *(*_xnew)(void), d2i_of_##type *_d2i, FILE *_in, type **_x) { \
+ return ASN1_d2i_fp((void *(*)(void))_xnew,(d2i_of_void*)_d2i,_in,(void*)_x) ; \
+ } \
+ ASN1_d2i_fp_of_##type(xnew,d2i,in,x); \
+ })
+#else
+# define ASN1_d2i_fp_of(type,xnew,d2i,in,x) \
((type *(*)(type *(*)(void),D2I_OF(type),FILE *,type **))openssl_fcast(ASN1_d2i_fp))(xnew,d2i,in,x)
+#endif
void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x);
int ASN1_i2d_fp(i2d_of_void *i2d,FILE *out,void *x);
-#define ASN1_i2d_fp_of(type,i2d,out,x) \
+#if defined(__GNUC__) && __GNUC__ >= 4
+# define ASN1_i2d_fp_of(type,i2d,out,x) \
+ ({ \
+ TYPEDEF_I2D_OF(type); \
+ int ASN1_i2d_fp_of_##type(i2d_of_##type *_i2d, FILE *_out, type *_x){ \
+ return ASN1_i2d_fp((i2d_of_void *)_i2d, _out, _x); \
+ } \
+ ASN1_i2d_fp_of_##type(i2d,out,x); \
+ })
+# define ASN1_i2d_fp_of_const(type,i2d,out,x) \
+ ({ \
+ TYPEDEF_I2D_OF_const(type); \
+ int ASN1_i2d_fp_of_const_##type(i2d_of_const_##type *_i2d, FILE *_out, type *_x){ \
+ return ASN1_i2d_fp((i2d_of_void *)_i2d, _out, _x); \
+ } \
+ ASN1_i2d_fp_of_const_##type(i2d,out,x); \
+ })
+
+#else
+# define ASN1_i2d_fp_of(type,i2d,out,x) \
((int (*)(I2D_OF(type),FILE *,type *))openssl_fcast(ASN1_i2d_fp))(i2d,out,x)
-#define ASN1_i2d_fp_of_const(type,i2d,out,x) \
+# define ASN1_i2d_fp_of_const(type,i2d,out,x) \
((int (*)(I2D_OF_const(type),FILE *,type *))openssl_fcast(ASN1_i2d_fp))(i2d,out,x)
+#endif
int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x);
int ASN1_STRING_print_ex_fp(FILE *fp, ASN1_STRING *str, unsigned long flags);
#endif
@@ -927,14 +978,45 @@

#ifndef OPENSSL_NO_BIO
void *ASN1_d2i_bio(void *(*xnew)(void), d2i_of_void *d2i, BIO *in, void **x);
-#define ASN1_d2i_bio_of(type,xnew,d2i,in,x) \
+#if defined(__GNUC__) && __GNUC__ >= 4
+# define ASN1_d2i_bio_of(type,xnew,d2i,in,x) \
+ ({ \
+ TYPEDEF_D2I_OF(type); \
+ type *ASN1_d2i_bio_of_##type(type *(*_xnew)(void), d2i_of_##type *_d2i, BIO *_in, type **_x) { \
+ return ASN1_d2i_bio((void *(*)(void)) _xnew, (d2i_of_void *) _d2i, _in, (void *)_x); \
+ } \
+ ASN1_d2i_bio_of_##type(xnew, d2i, in, x); \
+ })
+#else
+# define ASN1_d2i_bio_of(type,xnew,d2i,in,x) \
((type *(*)(type *(*)(void),D2I_OF(type),BIO *,type **))openssl_fcast(ASN1_d2i_bio))(xnew,d2i,in,x)
+#endif
void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x);
int ASN1_i2d_bio(i2d_of_void *i2d,BIO *out, unsigned char *x);
-#define ASN1_i2d_bio_of(type,i2d,out,x) \
+#if defined(__GNUC__) && __GNUC__ >= 4
+# define ASN1_i2d_bio_of(type,i2d,out,x) \
+ ({ \
+ TYPEDEF_I2D_OF(type); \
+ int ASN1_i2d_bio_of_##type(i2d_of_##type *_i2d, BIO *_out, type *_x) { \
+ return ASN1_i2d_bio((i2d_of_void *)_i2d, _out, (void *) _x); \
+ } \
+ ASN1_i2d_bio_of_##type(i2d, out, x); \
+ })
+# define ASN1_i2d_bio_of_const(type,i2d,out,x) \
+ ({ \
+ TYPEDEF_I2D_OF_const(type); \
+ int ASN1_i2d_bio_of_const_##type(i2d_of_const_##type *_i2d, \
+ BIO *_out, const type *_x) { \
+ return ASN1_i2d_bio((i2d_of_void *)_i2d, _out, (void *) _x); \
+ } \
+ ASN1_i2d_bio_of_const_##type(i2d, out, x); \
+ })
+#else
+# define ASN1_i2d_bio_of(type,i2d,out,x) \
((int (*)(I2D_OF(type),BIO *,type *))openssl_fcast(ASN1_i2d_bio))(i2d,out,x)
-#define ASN1_i2d_bio_of_const(type,i2d,out,x) \
+# define ASN1_i2d_bio_of_const(type,i2d,out,x) \
((int (*)(I2D_OF_const(type),BIO *,const type *))openssl_fcast(ASN1_i2d_bio))(i2d,out,x)
+#endif
int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x);
int ASN1_UTCTIME_print(BIO *fp,ASN1_UTCTIME *a);
int ASN1_GENERALIZEDTIME_print(BIO *fp,ASN1_GENERALIZEDTIME *a);
@@ -977,8 +1059,19 @@
void *ASN1_item_unpack(ASN1_STRING *oct, const ASN1_ITEM *it);
ASN1_STRING *ASN1_pack_string(void *obj, i2d_of_void *i2d,
ASN1_OCTET_STRING **oct);
-#define ASN1_pack_string_of(type,obj,i2d,oct) \
- ((ASN1_STRING *(*)(type *,I2D_OF(type),ASN1_OCTET_STRING **))openssl_fcast(ASN1_pack_string))(obj,i2d,oct)
+#if defined(__GNUC__) && __GNUC__ >= 4
+# define ASN1_pack_string_of(type,obj,i2d,oct) ({ \
+ TYPEDEF_I2D_OF(type); \
+ ASN1_STRING *ASN1_pack_string_of_##type(type * _obj, i2d_of_##type* _i2d, \
+ ASN1_OCTET_STRING **_oct) { \
+ return ASN1_pack_string(_obj, (i2d_of_void *)_i2d, _oct); \
+ } \
+ ASN1_pack_string_of_##type(obj, i2d, oct); \
+ })
+#else
+# define ASN1_pack_string_of(type,obj,i2d,oct) \
+ ((ASN1_STRING *(*)(type *,I2D_OF(type),ASN1_OCTET_STRING **))openssl_fcast(ASN1_pack_string))(obj,i2d,oct)
+#endif
ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_OCTET_STRING **oct);

void ASN1_STRING_set_default_mask(unsigned long mask);
diff -ru openssl-0.9.8e-orig/crypto/ocsp/ocsp.h openssl-0.9.8e/crypto/ocsp/ocsp.h
--- openssl-0.9.8e-orig/crypto/ocsp/ocsp.h Fri May 13 00:01:43 2005
+++ openssl-0.9.8e/crypto/ocsp/ocsp.h Fri Aug 31 16:13:15 2007
@@ -468,8 +468,19 @@

ASN1_STRING *ASN1_STRING_encode(ASN1_STRING *s, i2d_of_void *i2d,
void *data, STACK_OF(ASN1_OBJECT) *sk);
+#if defined(__GNUC__) && __GNUC__ >= 4
+#define ASN1_STRING_encode_of(type,s,i2d,data,sk) \
+ ({ \
+ TYPEDEF_I2D_OF(type); \
+ ASN1_STRING *ASN1_STRING_encode_of_##type(ASN1_STRING *_s, i2d_of_##type *_i2d, type*_data,STACK_OF(ASN1_OBJECT) *_sk){ \
+ return ASN1_STRING_encode(_s, (i2d_of_void*) _i2d,_data,_sk); \
+ } \
+ ASN1_STRING_encode_of_##type(s,i2d,data,sk); \
+ })
+#else
#define ASN1_STRING_encode_of(type,s,i2d,data,sk) \
((ASN1_STRING *(*)(ASN1_STRING *,I2D_OF(type),type *,STACK_OF(ASN1_OBJECT) *))openssl_fcast(ASN1_STRING_encode))(s,i2d,data,s k)
+#endif

X509_EXTENSION *OCSP_crlID_new(char *url, long *n, char *tim);

diff -ru openssl-0.9.8e-orig/crypto/pem/pem.h openssl-0.9.8e/crypto/pem/pem.h
--- openssl-0.9.8e-orig/crypto/pem/pem.h Tue Dec 19 19:47:36 2006
+++ openssl-0.9.8e/crypto/pem/pem.h Fri Aug 31 16:13:15 2007
@@ -220,70 +220,70 @@
#define IMPLEMENT_PEM_read_fp(name, type, str, asn1) \
type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u)\
{ \
-return(((type *(*)(D2I_OF(type),char *,FILE *,type **,pem_password_cb *,void *))openssl_fcast(PEM_ASN1_read))(d2i_##asn1, str,fp,x,cb,u)); \
+ return PEM_ASN1_read((d2i_of_void *) d2i_##asn1, str,fp,(void *)x,cb,u); \
}

#define IMPLEMENT_PEM_write_fp(name, type, str, asn1) \
int PEM_write_##name(FILE *fp, type *x) \
{ \
-return(((int (*)(I2D_OF(type),const char *,FILE *,type *, const EVP_CIPHER *,unsigned char *,int, pem_password_cb *,void *))openssl_fcast(PEM_ASN1_write))(i2d_##asn1,str,f p,x,NULL,NULL,0,NULL,NULL)); \
+ return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,(char *) x,NULL,NULL,0,NULL,NULL); \
}

#define IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) \
int PEM_write_##name(FILE *fp, const type *x) \
-{ \
-return(((int (*)(I2D_OF_const(type),const char *,FILE *, const type *, const EVP_CIPHER *,unsigned char *,int, pem_password_cb *,void *))openssl_fcast(PEM_ASN1_write))(i2d_##asn1,str,f p,x,NULL,NULL,0,NULL,NULL)); \
+{ \
+ return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp, (char *) x,NULL,NULL,0,NULL,NULL); \
}

-#define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) \
-int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \
- unsigned char *kstr, int klen, pem_password_cb *cb, \
- void *u) \
- { \
- return(((int (*)(I2D_OF(type),const char *,FILE *,type *, const EVP_CIPHER *,unsigned char *,int, pem_password_cb *,void *))openssl_fcast(PEM_ASN1_write))(i2d_##asn1,str,f p,x,enc,kstr,klen,cb,u)); \
- }
+#define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) \
+int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \
+ unsigned char *kstr, int klen, pem_password_cb *cb, \
+ void *u) \
+{ \
+ return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp, (char *)x,enc,kstr,klen,cb,u); \
+}

#define IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) \
int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \
- unsigned char *kstr, int klen, pem_password_cb *cb, \
- void *u) \
- { \
- return(((int (*)(I2D_OF_const(type),const char *,FILE *,type *, const EVP_CIPHER *,unsigned char *,int, pem_password_cb *,void *))openssl_fcast(PEM_ASN1_write))(i2d_##asn1,str,f p,x,enc,kstr,klen,cb,u)); \
- }
+ unsigned char *kstr, int klen, pem_password_cb *cb, \
+ void *u) \
+{ \
+ return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,(char *)x,enc,kstr,klen,cb,u); \
+}

#endif

#define IMPLEMENT_PEM_read_bio(name, type, str, asn1) \
type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u)\
{ \
-return(((type *(*)(D2I_OF(type),const char *,BIO *,type **,pem_password_cb *,void *))openssl_fcast(PEM_ASN1_read_bio))(d2i_##asn1, str,bp,x,cb,u)); \
+ return PEM_ASN1_read_bio((d2i_of_void *)d2i_##asn1, str,bp, (void *) x,cb,u); \
}

#define IMPLEMENT_PEM_write_bio(name, type, str, asn1) \
int PEM_write_bio_##name(BIO *bp, type *x) \
-{ \
-return(((int (*)(I2D_OF(type),const char *,BIO *,type *, const EVP_CIPHER *,unsigned char *,int, pem_password_cb *,void *))openssl_fcast(PEM_ASN1_write_bio))(i2d_##asn1,s tr,bp,x,NULL,NULL,0,NULL,NULL)); \
+{ \
+ return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,(char*)x,NULL,NULL,0,NULL,NULL ); \
}

#define IMPLEMENT_PEM_write_bio_const(name, type, str, asn1) \
int PEM_write_bio_##name(BIO *bp, const type *x) \
-{ \
-return(((int (*)(I2D_OF_const(type),const char *,BIO *,const type *, const EVP_CIPHER *,unsigned char *,int, pem_password_cb *,void *))openssl_fcast(PEM_ASN1_write_bio))(i2d_##asn1,s tr,bp,x,NULL,NULL,0,NULL,NULL)); \
+{ \
+ return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,(char *)x,NULL,NULL,0,NULL,NULL); \
}

#define IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \
int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \
- unsigned char *kstr, int klen, pem_password_cb *cb, void *u) \
- { \
- return(((int (*)(I2D_OF(type),const char *,BIO *,type *,const EVP_CIPHER *,unsigned char *,int,pem_password_cb *,void *))openssl_fcast(PEM_ASN1_write_bio))(i2d_##asn1,s tr,bp,x,enc,kstr,klen,cb,u)); \
- }
+ unsigned char *kstr, int klen, pem_password_cb *cb, void *u) \
+{ \
+ return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,(char *)x,enc,kstr,klen,cb,u); \
+}

#define IMPLEMENT_PEM_write_cb_bio_const(name, type, str, asn1) \
int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \
unsigned char *kstr, int klen, pem_password_cb *cb, void *u) \
- { \
- return(((int (*)(I2D_OF_const(type),const char *,BIO *,type *,const EVP_CIPHER *,unsigned char *,int,pem_password_cb *,void *))openssl_fcast(PEM_ASN1_write_bio))(i2d_##asn1,s tr,bp,x,enc,kstr,klen,cb,u)); \
- }
+{ \
+ return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,(char *)x,enc,kstr,klen,cb,u); \
+}

#define IMPLEMENT_PEM_write(name, type, str, asn1) \
IMPLEMENT_PEM_write_bio(name, type, str, asn1) \
@@ -545,13 +545,46 @@
pem_password_cb *cb, void *u);
void * PEM_ASN1_read_bio(d2i_of_void *d2i, const char *name, BIO *bp,
void **x, pem_password_cb *cb, void *u);
-#define PEM_ASN1_read_bio_of(type,d2i,name,bp,x,cb,u) \
+#if defined(__GNUC__) && __GNUC__ >= 4
+# define PEM_ASN1_read_bio_of(type,d2i,name,bp,x,cb,u) \
+ ({ \
+ TYPEDEF_D2I_OF(type); \
+ type *PEM_ASN1_read_bio_of_##type(d2i_of_##type *_d2i, \
+ const char *_name, BIO *_bp, \
+ type **_x, pem_password_cb*_cb, \
+ void *_u) { \
+ return PEM_ASN1_read_bio((d2i_of_void *)_d2i, _name, _bp, \
+ (void *)_x, _cb, _u); \
+ } \
+ PEM_ASN1_read_bio_of_##type(d2i, name, bp, x, cb, u); \
+ })
+#else
+# define PEM_ASN1_read_bio_of(type,d2i,name,bp,x,cb,u) \
((type *(*)(D2I_OF(type),const char *,BIO *,type **,pem_password_cb *,void *))openssl_fcast(PEM_ASN1_read_bio))(d2i,name,bp,x ,cb,u)
+#endif
int PEM_ASN1_write_bio(i2d_of_void *i2d,const char *name,BIO *bp,char *x,
const EVP_CIPHER *enc,unsigned char *kstr,int klen,
pem_password_cb *cb, void *u);
-#define PEM_ASN1_write_bio_of(type,i2d,name,bp,x,enc,kstr, klen,cb,u) \
+#if defined(__GNUC__) && __GNUC__ >= 4
+# define PEM_ASN1_write_bio_of(type,i2d,name,bp,x,enc,kstr, klen,cb,u) \
+ ({ \
+ TYPEDEF_I2D_OF(type); \
+ int PEM_ASN1_write_bio_of_##type(i2d_of_##type *_i2d, \
+ const char *_name, BIO *_bp, \
+ type *_x, const EVP_CIPHER*_enc, \
+ unsigned char *_kstr, int _klen, \
+ pem_password_cb *_cb, void *_u){ \
+ return PEM_ASN1_write_bio((i2d_of_void *) _i2d, _name, _bp, \
+ (char *) _x, _enc, _kstr, _klen, \
+ _cb, _u); \
+ } \
+ PEM_ASN1_write_bio_of_##type(i2d, name, bp, x, enc, kstr, \
+ klen, cb, u); \
+ })
+#else
+# define PEM_ASN1_write_bio_of(type,i2d,name,bp,x,enc,kstr, klen,cb,u) \
((int (*)(I2D_OF(type),const char *,BIO *,type *, const EVP_CIPHER *,unsigned char *,int, pem_password_cb *,void *))openssl_fcast(PEM_ASN1_write_bio))(i2d,name,bp, x,enc,kstr,klen,cb,u)
+#endif

STACK_OF(X509_INFO) * PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *u);
int PEM_X509_INFO_write_bio(BIO *bp,X509_INFO *xi, EVP_CIPHER *enc,
diff -ru openssl-0.9.8e-orig/crypto/stack/safestack.h openssl-0.9.8e/crypto/stack/safestack.h
--- openssl-0.9.8e-orig/crypto/stack/safestack.h Fri Feb 23 01:01:08 2007
+++ openssl-0.9.8e/crypto/stack/safestack.h Fri Aug 31 16:13:15 2007
@@ -164,8 +164,18 @@
sk_num(st)
#define SKM_sk_value(type, st,i) \
((type *)sk_value(st, i))
-#define SKM_sk_set(type, st,i,val) \
+#if defined(__GNUC__) && __GNUC__ >= 4
+# define SKM_sk_set(type, st,i,val) \
+ ({ \
+ type *sk_set_##type(STACK_OF(type) *_st, int _i, type *_val) { \
+ return (type *) sk_set(_st, _i, (char *) _val); \
+ } \
+ sk_set_##type(st, i, val); \
+ })
+#else
+# define SKM_sk_set(type, st,i,val) \
((type *)sk_set(st, i,(char *)val))
+#endif
#define SKM_sk_zero(type, st) \
sk_zero(st)
#define SKM_sk_push(type, st,val) \
@@ -174,15 +184,45 @@
sk_unshift(st, val)
#define SKM_sk_find(type, st,val) \
sk_find(st, (char *)val)
-#define SKM_sk_delete(type, st,i) \
+#if defined(__GNUC__) && __GNUC__ >= 4
+# define SKM_sk_delete(type, st,i) \
+ ({ \
+ type *sk_delete_##type(STACK_OF(type) *_st, int _i) { \
+ return (type *) sk_delete(_st, _i); \
+ } \
+ sk_delete_##type(st, i); \
+ })
+# define SKM_sk_delete_ptr(type, st,ptr) \
+ ({ \
+ type *sk_delete_ptr_##type(STACK_OF(type) *_st, type* _ptr) { \
+ return (type *)sk_delete_ptr(_st, (char *)_ptr); \
+ } \
+ sk_delete_ptr_##type(st, ptr); \
+ })
+
+#else
+# define SKM_sk_delete(type, st,i) \
((type *)sk_delete(st, i))
-#define SKM_sk_delete_ptr(type, st,ptr) \
+# define SKM_sk_delete_ptr(type, st,ptr) \
((type *)sk_delete_ptr(st,(char *)ptr))
+#endif
#define SKM_sk_insert(type, st,val,i) \
sk_insert(st, (char *)val, i)
-#define SKM_sk_set_cmp_func(type, st,cmp) \
+#if defined(__GNUC__) && __GNUC__ >= 4
+# define SKM_sk_set_cmp_func(type, st,cmp) \
+ ({ \
+ typedef int (*cmp_func_##type)(const type*const*, const type*const*); \
+ typedef int (*cmp_func_t)(const char*const*, const char*const*); \
+ cmp_func_##type SKM_sk_set_cmp_func_##type(STACK_OF(type)*_st,cmp_ func_##type _cmp) { \
+ return (cmp_func_##type)sk_set_cmp_func(_st, (cmp_func_t)_cmp); \
+ } \
+ SKM_sk_set_cmp_func_##type(st, cmp); \
+ })
+#else
+# define SKM_sk_set_cmp_func(type, st,cmp) \
((int (*)(const type * const *,const type * const *)) \
sk_set_cmp_func(st, (int (*)(const char * const *, const char * const *))(cmp)))
+#endif
#define SKM_sk_dup(type, st) \
sk_dup(st)
#define SKM_sk_pop_free(type, st,free_func) \

------------=_1188905019-46503-1--
__________________________________________________ ____________________
OpenSSL Project http://www.openssl.org
Development Mailing List openssl-dev@openssl.org
Automated List Manager majordomo@openssl.org