Fix bug#305: pkt_dname_tolower could read beyond end of buffer or

get into an endless loop, if 0x20 was enabled, and buffers are small
  or particular broken packets are received.


git-svn-id: file:///svn/unbound/trunk@2072 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2010-04-09 09:04:07 +00:00
parent 560f4aab03
commit 36c46a8f71
2 changed files with 54 additions and 0 deletions

View file

@ -795,12 +795,53 @@ dname_test_valid()
, 4096) == 0);
}
/** test pkt_dname_tolower */
static void
dname_test_pdtl(ldns_buffer* loopbuf, ldns_buffer* boundbuf)
{
unit_show_func("util/data/dname.c", "pkt_dname_tolower");
pkt_dname_tolower(loopbuf, ldns_buffer_at(loopbuf, 12));
pkt_dname_tolower(boundbuf, ldns_buffer_at(boundbuf, 12));
}
/** setup looped dname and out-of-bounds dname ptr */
static void
dname_setup_bufs(ldns_buffer* loopbuf, ldns_buffer* boundbuf)
{
ldns_buffer_write_u16(loopbuf, 0xd54d); /* id */
ldns_buffer_write_u16(loopbuf, 0x12); /* flags */
ldns_buffer_write_u16(loopbuf, 1); /* qdcount */
ldns_buffer_write_u16(loopbuf, 0); /* ancount */
ldns_buffer_write_u16(loopbuf, 0); /* nscount */
ldns_buffer_write_u16(loopbuf, 0); /* arcount */
ldns_buffer_write_u8(loopbuf, 0xc0); /* PTR back at itself */
ldns_buffer_write_u8(loopbuf, 0x0c);
ldns_buffer_flip(loopbuf);
ldns_buffer_write_u16(boundbuf, 0xd54d); /* id */
ldns_buffer_write_u16(boundbuf, 0x12); /* flags */
ldns_buffer_write_u16(boundbuf, 1); /* qdcount */
ldns_buffer_write_u16(boundbuf, 0); /* ancount */
ldns_buffer_write_u16(boundbuf, 0); /* nscount */
ldns_buffer_write_u16(boundbuf, 0); /* arcount */
ldns_buffer_write_u8(boundbuf, 0x01); /* len=1 */
ldns_buffer_write_u8(boundbuf, 'A'); /* A. label */
ldns_buffer_write_u8(boundbuf, 0xc0); /* PTR out of bounds */
ldns_buffer_write_u8(boundbuf, 0xcc);
ldns_buffer_flip(boundbuf);
}
void dname_test()
{
ldns_buffer* loopbuf = ldns_buffer_new(14);
ldns_buffer* boundbuf = ldns_buffer_new(16);
ldns_buffer* buff = ldns_buffer_new(65800);
unit_assert(loopbuf && boundbuf && buff);
ldns_buffer_flip(buff);
dname_setup_bufs(loopbuf, boundbuf);
dname_test_qdl(buff);
dname_test_qdtl(buff);
dname_test_pdtl(loopbuf, boundbuf);
dname_test_query_dname_compare();
dname_test_count_labels();
dname_test_count_size_labels();
@ -816,4 +857,6 @@ void dname_test()
dname_test_topdomain();
dname_test_valid();
ldns_buffer_free(buff);
ldns_buffer_free(loopbuf);
ldns_buffer_free(boundbuf);
}

View file

@ -148,17 +148,28 @@ void
pkt_dname_tolower(ldns_buffer* pkt, uint8_t* dname)
{
uint8_t lablen;
int count = 0;
if(dname >= ldns_buffer_end(pkt))
return;
lablen = *dname++;
while(lablen) {
if(LABEL_IS_PTR(lablen)) {
if(PTR_OFFSET(lablen, *dname) >= ldns_buffer_limit(pkt))
return;
dname = ldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname));
lablen = *dname++;
if(count++ > MAX_COMPRESS_PTRS)
return;
continue;
}
if(dname+lablen >= ldns_buffer_end(pkt))
return;
while(lablen--) {
*dname = (uint8_t)tolower((int)*dname);
dname++;
}
if(dname >= ldns_buffer_end(pkt))
return;
lablen = *dname++;
}
}