GnuTLS does not build on OS X 10.6 due to incompatibility with snprintf macro

Camillo Lugaresi camillo.lugaresi at gmail.com
Wed Dec 29 05:26:42 CET 2010


Code built with gcc on Mac OS X 10.6 uses the object size checking feature of gcc by default (<http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html>). This involves redefining several functions as macros; one of these functions is snprintf:

	#define snprintf(str, len, ...) \
 	 __builtin___snprintf_chk (str, len, 0, __darwin_obsz(str), __VA_ARGS__)

The usage of snprintf in src/serv.c in gnutls-2.10.4 is not compatible with that macro. serv.c attempts to use a macro (tmp2) that expands into two different arguments:

	#define tmp2 &http_buffer[strlen(http_buffer)], len-strlen(http_buffer)

	snprintf (tmp2, "%.2X", sesid[i]);

Due to how nested macro evaluation works, the snprintf macro sees tmp2 as a single argument, and copies it into __darwin_obsz(); then, when tmp2 is expanded, __darwin_obsz has two arguments, but it is only defined for one, and the result is a compilation error.

One way to work around this issue might be to define _FORTIFY_SOURCE=0 so that the snprintf macro is not defined, or simply doing an #undef snprintf for that file, but it seems safer and more portable to split tmp2 into two macros. I append a patch that does so.

Best regards,
Camillo Lugaresi


diff --git a/src/serv.c b/src/serv.c
index 0307b05..4b6658d 100644
--- a/src/serv.c
+++ b/src/serv.c
@@ -438,7 +438,8 @@ static const char DEFAULT_DATA[] =
 
 /* Creates html with the current session information.
  */
-#define tmp2 &http_buffer[strlen(http_buffer)], len-strlen(http_buffer)
+#define tmp2b &http_buffer[strlen(http_buffer)]
+#define tmp2l len-strlen(http_buffer)
 static char *
 peer_print_info (gnutls_session_t session, int *ret_length,
 		 const char *header)
@@ -512,11 +513,11 @@ peer_print_info (gnutls_session_t session, int *ret_length,
 
   /* print session_id */
   gnutls_session_get_id (session, sesid, &sesid_size);
-  snprintf (tmp2, "\n<p>Session ID: <i>");
+  snprintf (tmp2b, tmp2l, "\n<p>Session ID: <i>");
   for (i = 0; i < sesid_size; i++)
-    snprintf (tmp2, "%.2X", sesid[i]);
-  snprintf (tmp2, "</i></p>\n");
-  snprintf (tmp2,
+    snprintf (tmp2b, tmp2l, "%.2X", sesid[i]);
+  snprintf (tmp2b, tmp2l, "</i></p>\n");
+  snprintf (tmp2b, tmp2l,
 	   "<h5>If your browser supports session resuming, then you should see the "
 	   "same session ID, when you press the <b>reload</b> button.</h5>\n");
 
@@ -530,7 +531,7 @@ peer_print_info (gnutls_session_t session, int *ret_length,
 
     if (gnutls_server_name_get (session, dns, &dns_size, &type, 0) == 0)
       {
-	snprintf (tmp2, "\n<p>Server Name: %s</p>\n", dns);
+	snprintf (tmp2b, tmp2l, "\n<p>Server Name: %s</p>\n", dns);
       }
 
   }
@@ -541,7 +542,7 @@ peer_print_info (gnutls_session_t session, int *ret_length,
 #ifdef ENABLE_SRP
   if (kx_alg == GNUTLS_KX_SRP)
     {
-      snprintf (tmp2, "<p>Connected as user '%s'.</p>\n",
+      snprintf (tmp2b, tmp2l, "<p>Connected as user '%s'.</p>\n",
 	       gnutls_srp_server_get_username (session));
     }
 #endif
@@ -549,7 +550,7 @@ peer_print_info (gnutls_session_t session, int *ret_length,
 #ifdef ENABLE_PSK
   if (kx_alg == GNUTLS_KX_PSK)
     {
-      snprintf (tmp2, "<p>Connected as user '%s'.</p>\n",
+      snprintf (tmp2b, tmp2l, "<p>Connected as user '%s'.</p>\n",
 	       gnutls_psk_server_get_username (session));
     }
 #endif
@@ -557,7 +558,7 @@ peer_print_info (gnutls_session_t session, int *ret_length,
 #ifdef ENABLE_ANON
   if (kx_alg == GNUTLS_KX_ANON_DH)
     {
-      snprintf (tmp2,
+      snprintf (tmp2b, tmp2l,
 	       "<p> Connect using anonymous DH (prime of %d bits)</p>\n",
 	       gnutls_dh_get_prime_bits (session));
     }
@@ -565,7 +566,7 @@ peer_print_info (gnutls_session_t session, int *ret_length,
 
   if (kx_alg == GNUTLS_KX_DHE_RSA || kx_alg == GNUTLS_KX_DHE_DSS)
     {
-      snprintf (tmp2,
+      snprintf (tmp2b, tmp2l,
 	       "Ephemeral DH using prime of <b>%d</b> bits.<br>\n",
 	       gnutls_dh_get_prime_bits (session));
     }
@@ -576,7 +577,7 @@ peer_print_info (gnutls_session_t session, int *ret_length,
   tmp = gnutls_protocol_get_name (gnutls_protocol_get_version (session));
   if (tmp == NULL)
     tmp = str_unknown;
-  snprintf (tmp2,
+  snprintf (tmp2b, tmp2l,
 	   "<TABLE border=1><TR><TD>Protocol version:</TD><TD>%s</TD></TR>\n",
 	   tmp);
 
@@ -587,44 +588,44 @@ peer_print_info (gnutls_session_t session, int *ret_length,
 					  (session));
       if (tmp == NULL)
 	tmp = str_unknown;
-      snprintf (tmp2, "<TR><TD>Certificate Type:</TD><TD>%s</TD></TR>\n", tmp);
+      snprintf (tmp2b, tmp2l, "<TR><TD>Certificate Type:</TD><TD>%s</TD></TR>\n", tmp);
     }
 
   tmp = gnutls_kx_get_name (kx_alg);
   if (tmp == NULL)
     tmp = str_unknown;
-  snprintf (tmp2, "<TR><TD>Key Exchange:</TD><TD>%s</TD></TR>\n", tmp);
+  snprintf (tmp2b, tmp2l, "<TR><TD>Key Exchange:</TD><TD>%s</TD></TR>\n", tmp);
 
   tmp = gnutls_compression_get_name (gnutls_compression_get (session));
   if (tmp == NULL)
     tmp = str_unknown;
-  snprintf (tmp2, "<TR><TD>Compression</TD><TD>%s</TD></TR>\n", tmp);
+  snprintf (tmp2b, tmp2l, "<TR><TD>Compression</TD><TD>%s</TD></TR>\n", tmp);
 
   tmp = gnutls_cipher_get_name (gnutls_cipher_get (session));
   if (tmp == NULL)
     tmp = str_unknown;
-  snprintf (tmp2, "<TR><TD>Cipher</TD><TD>%s</TD></TR>\n", tmp);
+  snprintf (tmp2b, tmp2l, "<TR><TD>Cipher</TD><TD>%s</TD></TR>\n", tmp);
 
   tmp = gnutls_mac_get_name (gnutls_mac_get (session));
   if (tmp == NULL)
     tmp = str_unknown;
-  snprintf (tmp2, "<TR><TD>MAC</TD><TD>%s</TD></TR>\n", tmp);
+  snprintf (tmp2b, tmp2l, "<TR><TD>MAC</TD><TD>%s</TD></TR>\n", tmp);
 
   tmp = gnutls_cipher_suite_get_name (kx_alg,
 				      gnutls_cipher_get (session),
 				      gnutls_mac_get (session));
   if (tmp == NULL)
     tmp = str_unknown;
-  snprintf (tmp2, "<TR><TD>Ciphersuite</TD><TD>%s</TD></TR></p></TABLE>\n",
+  snprintf (tmp2b, tmp2l, "<TR><TD>Ciphersuite</TD><TD>%s</TD></TR></p></TABLE>\n",
 	   tmp);
 
   if (crtinfo)
     {
-      snprintf(tmp2, "<hr><PRE>%s\n</PRE>\n", crtinfo);
+      snprintf(tmp2b, tmp2l, "<hr><PRE>%s\n</PRE>\n", crtinfo);
       free (crtinfo);
     }
 
-  snprintf(tmp2, "<hr><P>Your HTTP header was:<PRE>%s</PRE></P>\n" HTTP_END, header);
+  snprintf(tmp2b, tmp2l, "<hr><P>Your HTTP header was:<PRE>%s</PRE></P>\n" HTTP_END, header);
 
   *ret_length = strlen (http_buffer);
 





More information about the Gnutls-devel mailing list