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