File squid-3.1.11-bnc727492-CVE-2011-4096_invalid_free_CNAME.diff of Package squid3.import5582

diff -rNU 30 ../squid-3.1.11-o/lib/rfc1035.c ./lib/rfc1035.c
--- ../squid-3.1.11-o/lib/rfc1035.c	2011-02-08 05:05:51.000000000 +0100
+++ ./lib/rfc1035.c	2011-12-21 14:39:03.000000000 +0100
@@ -452,65 +452,65 @@
         break;
     case 2:
         rfc1035_error_message = "Server Failure: The name server was "
                                 "unable to process this query.";
         break;
     case 3:
         rfc1035_error_message = "Name Error: The domain name does "
                                 "not exist.";
         break;
     case 4:
         rfc1035_error_message = "Not Implemented: The name server does "
                                 "not support the requested kind of query.";
         break;
     case 5:
         rfc1035_error_message = "Refused: The name server refuses to "
                                 "perform the specified operation.";
         break;
     case rfc1035_unpack_error:
         rfc1035_error_message = "The DNS reply message is corrupt or could "
                                 "not be safely parsed.";
         break;
     default:
         rfc1035_error_message = "Unknown Error";
         break;
     }
 }
 
 void
 rfc1035RRDestroy(rfc1035_rr ** rr, int n)
 {
-    if (*rr == NULL || n < 1) {
+    if (*rr == NULL) {
         return;
     }
 
-    while (n--) {
+    while (n-- > 0) {
         if ((*rr)[n].rdata)
             xfree((*rr)[n].rdata);
     }
     xfree(*rr);
     *rr = NULL;
 }
 
 /*
  * rfc1035QueryUnpack()
  *
  * Unpacks a RFC1035 Query Record into 'query' from a message buffer.
  *
  * Updates the new message buffer offset.
  *
  * Returns 0 (success) or 1 (error)
  */
 static int
 rfc1035QueryUnpack(const char *buf, size_t sz, unsigned int *off, rfc1035_query * query)
 {
     unsigned short s;
     if (rfc1035NameUnpack(buf, sz, off, NULL, query->name, RFC1035_MAXHOSTNAMESZ, 0)) {
         RFC1035_UNPACK_DEBUG;
         memset(query, '\0', sizeof(*query));
         return 1;
     }
     if (*off + 4 > sz) {
         RFC1035_UNPACK_DEBUG;
         memset(query, '\0', sizeof(*query));
         return 1;
     }
diff -rNU 30 ../squid-3.1.11-o/src/dns_internal.cc ./src/dns_internal.cc
--- ../squid-3.1.11-o/src/dns_internal.cc	2011-02-08 05:05:51.000000000 +0100
+++ ./src/dns_internal.cc	2011-12-21 14:40:11.000000000 +0100
@@ -1083,70 +1083,71 @@
 
         // reset the query as an A query
         q->nsends = 0;
         q->start_t = current_time;
         q->id = idnsQueryID();
         rfc1035SetQueryID(q->buf, q->id);
         q->sz = rfc3596BuildAQuery(q->name, q->buf, sizeof(q->buf), q->id, &q->query);
         q->need_A = false;
         idnsCacheQuery(q);
         idnsSendQuery(q);
         return;
     }
 
     /** If there are two result sets from preceeding AAAA and A lookups merge them with a preference for AAAA */
     if (q->initial_AAAA.count > 0 && n > 0) {
         /* two sets of RR need merging */
         rfc1035_rr *result = (rfc1035_rr*) xmalloc( sizeof(rfc1035_rr)*(n + q->initial_AAAA.count) );
         rfc1035_rr *tmp = result;
 
         debugs(78, 6, HERE << "Merging DNS results " << q->name << " AAAA has " << q->initial_AAAA.count << " RR, A has " << n << " RR");
 
         memcpy(tmp, q->initial_AAAA.answers, (sizeof(rfc1035_rr)*(q->initial_AAAA.count)) );
         tmp += q->initial_AAAA.count;
         /* free the RR object without freeing its child strings (they are now taken by the copy above) */
         safe_free(q->initial_AAAA.answers);
 
         memcpy( tmp, message->answer, (sizeof(rfc1035_rr)*n) );
         /* free the RR object without freeing its child strings (they are now taken by the copy above) */
         safe_free(message->answer);
 
-        message->answer = result;
-        message->ancount += q->initial_AAAA.count;
         n += q->initial_AAAA.count;
-        q->initial_AAAA.count=0;
+        q->initial_AAAA.count = 0;
+        message->answer = result;
+        message->ancount = n;
     } else if (q->initial_AAAA.count > 0 && n <= 0) {
         /* initial of dual queries was the only result set. */
         debugs(78, 6, HERE << "Merging DNS results " << q->name << " AAAA has " << q->initial_AAAA.count << " RR, A has " << n << " RR");
         rfc1035RRDestroy(&(message->answer), n);
         message->answer = q->initial_AAAA.answers;
         n = q->initial_AAAA.count;
+        message->ancount = n;
     }
     /* else initial results were empty. just use the final set as authoritative */
 
     debugs(78, 6, HERE << "Sending " << n << " DNS results to caller.");
     idnsCallback(q, message->answer, n, q->error);
     rfc1035MessageDestroy(&message);
     cbdataFree(q);
 }
 
 static void
 idnsRead(int fd, void *data)
 {
     int *N = &incoming_sockets_accepted;
     int len;
     int max = INCOMING_DNS_MAX;
     static char rbuf[SQUID_UDP_SO_RCVBUF];
     int ns;
     IpAddress from;
 
     debugs(78, 3, "idnsRead: starting with FD " << fd);
 
     // Always keep reading. This stops (or at least makes harder) several
     // attacks on the DNS client.
     commSetSelect(fd, COMM_SELECT_READ, idnsRead, NULL, 0);
 
     /* BUG (UNRESOLVED)
      *  two code lines after returning from comm_udprecvfrom()
      *  something overwrites the memory behind the from parameter.
      *  NO matter where in the stack declaration list above it is placed
      *  The cause of this is still unknown, however copying the data appears