Fix stack-smashing crash in DNSSEC. Thanks to Henk Jan Agteresch.
diff --git a/src/cache.c b/src/cache.c
index 19a5d61..66b52d2 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -55,7 +55,9 @@
   { 41,  "OPT" },
   { 43,  "DS" },
   { 46,  "RRSIG" },
+  { 47,  "NSEC" },
   { 48,  "DNSKEY" },
+  { 50,  "NSEC3" },
   { 249, "TKEY" },
   { 250, "TSIG" },
   { 251, "IXFR" },
@@ -1301,12 +1303,10 @@
 	      {
 		if (cache->flags & F_DNSKEY)
 		  {
-		    char tp[20];
 		    /* RRSIG */
-		    querystr("", tp, cache->addr.sig.type_covered);
 		    a = daemon->addrbuff;
 		    sprintf(a, "%5u %3u %s", cache->addr.sig.keytag,
-			    cache->addr.sig.algo, tp);
+			    cache->addr.sig.algo, querystr("", cache->addr.sig.type_covered));
 		  }
 		else
 		  {
@@ -1382,14 +1382,45 @@
   return "<unknown>";
 }
 
-void querystr(char *desc, char *str, unsigned short type)
+char *querystr(char *desc, unsigned short type)
 {
   unsigned int i;
-  
-  sprintf(str, "%s[type=%d]", desc, type); 
+  int len = 10; /* strlen("type=xxxxx") */
+  const char *types = NULL;
+  static char *buff = NULL;
+  static int bufflen = 0;
+
   for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++)
     if (typestr[i].type == type)
-      sprintf(str,"%s[%s]", desc, typestr[i].name);
+      {
+	types = typestr[i].name;
+	len = strlen(types);
+	break;
+      }
+
+  len += 3; /* braces, terminator */
+  len += strlen(desc);
+
+  if (!buff || bufflen < len)
+    {
+      if (buff)
+	free(buff);
+      else if (len < 20)
+	len = 20;
+      
+      buff = whine_malloc(len);
+      bufflen = len;
+    }
+
+  if (buff)
+    {
+      if (types)
+	sprintf(buff, "%s[%s]", desc, types);
+      else
+	sprintf(buff, "%s[type=%d]", desc, type);
+    }
+
+  return buff ? buff : "";
 }
 
 void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 58a4fe2..a84ac36 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -991,7 +991,7 @@
 void cache_init(void);
 void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg); 
 char *record_source(int index);
-void querystr(char *desc, char *str, unsigned short type);
+char *querystr(char *desc, unsigned short type);
 struct crec *cache_find_by_addr(struct crec *crecp,
 				struct all_addr *addr, time_t now, 
 				unsigned int prot);
diff --git a/src/dnssec.c b/src/dnssec.c
index 7a69528..8263b3e 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -1387,9 +1387,7 @@
 size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class, int type, union mysockaddr *addr)
 {
   unsigned char *p;
-  char types[20];
-  
-  querystr("dnssec-query", types, type);
+  char *types = querystr("dnssec-query", type);
 
   if (addr->sa.sa_family == AF_INET) 
     log_query(F_DNSSEC | F_IPV4, name, (struct all_addr *)&addr->in.sin_addr, types);
diff --git a/src/forward.c b/src/forward.c
index ed853a3..073b2c9 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -1117,13 +1117,11 @@
   
   if (extract_request(header, (size_t)n, daemon->namebuff, &type))
     {
-      char types[20];
 #ifdef HAVE_AUTH
       struct auth_zone *zone;
 #endif
-
-      querystr(auth_dns ? "auth" : "query", types, type);
-
+      char *types = querystr(auth_dns ? "auth" : "query", type);
+      
       if (listen->family == AF_INET) 
 	log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff, 
 		  (struct all_addr *)&source_addr.in.sin_addr, types);
@@ -1290,11 +1288,10 @@
       
       if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
 	{
-	  char types[20];
 #ifdef HAVE_AUTH
 	  struct auth_zone *zone;
 #endif
-	  querystr(auth_dns ? "auth" : "query", types, qtype);
+	  char *types = querystr(auth_dns ? "auth" : "query", qtype);
 	  
 	  if (peer_addr.sa.sa_family == AF_INET) 
 	    log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff, 
diff --git a/src/rfc1035.c b/src/rfc1035.c
index 26cda15..ac8c4ae 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -1628,11 +1628,7 @@
 		    (keydata = blockdata_retrieve(crecp->addr.sig.keydata, crecp->addr.sig.keylen, NULL)))
 		  {
 		    if (qtype == T_RRSIG)
-		      {
-			char types[20];
-			querystr("rrsig", types, crecp->addr.sig.type_covered);
-			log_query(F_RRNAME, name, NULL, types);
-		      }
+		      log_query(F_RRNAME, name, NULL, querystr("rrsig", crecp->addr.sig.type_covered));
 		    if ((keydata = blockdata_retrieve(crecp->addr.sig.keydata, crecp->addr.sig.keylen, NULL)) &&
 			add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
 					    crec_ttl(crecp, now), &nameoffset,