From 6c7416128c35c3f792220cdc78ec6f940fa2e7f4 Mon Sep 17 00:00:00 2001 From: Wouter Wijngaards Date: Wed, 5 Nov 2008 10:38:22 +0000 Subject: [PATCH] fixup memleaks. git-svn-id: file:///svn/unbound/trunk@1331 be551aaa-1e26-0410-a405-d3ace91eadb9 --- daemon/worker.c | 6 +++++- doc/Changelog | 12 +++++++++++ services/cache/dns.c | 2 +- services/mesh.c | 10 +++++++++ services/mesh.h | 3 +++ util/configparser.c | 47 +++++++++++++++++++++--------------------- util/configparser.y | 1 + util/data/msgencode.c | 8 +++++-- validator/val_kentry.c | 1 + validator/val_neg.c | 1 + 10 files changed, 64 insertions(+), 27 deletions(-) diff --git a/daemon/worker.c b/daemon/worker.c index 7ab97c592..856b0be9a 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -820,8 +820,12 @@ worker_handle_request(struct comm_point* c, void* arg, int error, } if(local_zones_answer(worker->daemon->local_zones, &qinfo, &edns, c->buffer, worker->scratchpad)) { + if(ldns_buffer_limit(c->buffer) == 0) { + comm_point_drop_reply(repinfo); + return 0; + } server_stats_insrcode(&worker->stats, c->buffer); - return (ldns_buffer_limit(c->buffer) != 0); + return 1; } if(!(LDNS_RD_WIRE(ldns_buffer_begin(c->buffer))) && acl != acl_allow_snoop ) { diff --git a/doc/Changelog b/doc/Changelog index 646628408..a8c125980 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,15 @@ +5 November 2008: Wouter + - fixed possible memory leak in key_entry_key deletion. + Would leak a couple bytes when trust anchors were replaced. + - if query and reply qname overlap, the bytes are skipped not copied. + - fixed file descriptor leak when messages were jostled out that + had outstanding (TCP) replies. + - DNAMEs used from cache have their synthesized CNAMEs initialized + properly. + - fixed file descriptor leak for localzone type deny (for TCP). + - fixed memleak at exit for nsec3 negative cached zones. + - fixed memleak for the keyword 'nodefault' when reading config. + 4 November 2008: Wouter - fixed -Wwrite-strings warnings that result in better code. diff --git a/services/cache/dns.c b/services/cache/dns.c index 742f0387f..7f033803f 100644 --- a/services/cache/dns.c +++ b/services/cache/dns.c @@ -483,7 +483,7 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region, return NULL; ck->rk.dname_len = q->qname_len; ck->entry.hash = rrset_key_hash(&ck->rk); - newd = (struct packed_rrset_data*)regional_alloc(region, + newd = (struct packed_rrset_data*)regional_alloc_zero(region, sizeof(struct packed_rrset_data) + sizeof(size_t) + sizeof(uint8_t*) + sizeof(uint32_t) + sizeof(uint16_t) + newlen); diff --git a/services/mesh.c b/services/mesh.c index b3ad7f2a2..8573b7795 100644 --- a/services/mesh.c +++ b/services/mesh.c @@ -397,6 +397,7 @@ mesh_state_create(struct module_env* env, struct query_info* qinfo, mstate->run_node.key = mstate; mstate->reply_list = NULL; mstate->list_select = mesh_no_list; + mstate->replies_sent = 0; rbtree_init(&mstate->super_set, &mesh_state_ref_compare); rbtree_init(&mstate->sub_set, &mesh_state_ref_compare); mstate->num_activated = 0; @@ -435,6 +436,14 @@ mesh_state_cleanup(struct mesh_state* mstate) int i; if(!mstate) return; + /* drop unsent replies */ + if(!mstate->replies_sent) { + struct mesh_reply* rep; + for(rep=mstate->reply_list; rep; rep=rep->next) { + comm_point_drop_reply(&rep->query_reply); + } + } + /* de-init modules */ mesh = mstate->s.env->mesh; for(i=0; imods.num; i++) { @@ -700,6 +709,7 @@ void mesh_query_done(struct mesh_state* mstate) mesh_send_reply(mstate, mstate->s.return_rcode, rep, r, prev); prev = r; } + mstate->replies_sent = 1; for(c = mstate->cb_list; c; c = c->next) { mesh_do_callback(mstate, mstate->s.return_rcode, rep, c); } diff --git a/services/mesh.h b/services/mesh.h index 61c5bd111..0a0d7de79 100644 --- a/services/mesh.h +++ b/services/mesh.h @@ -168,6 +168,9 @@ struct mesh_state { /** if this state is in the forever list, jostle list, or neither */ enum mesh_list_select { mesh_no_list, mesh_forever_list, mesh_jostle_list } list_select; + + /** true if replies have been sent out (at end for alignment) */ + uint8_t replies_sent; }; /** diff --git a/util/configparser.c b/util/configparser.c index fc7621b58..d4090d7d6 100644 --- a/util/configparser.c +++ b/util/configparser.c @@ -709,10 +709,10 @@ static const yytype_uint16 yyrline[] = 475, 482, 489, 500, 508, 521, 530, 539, 547, 560, 569, 578, 587, 596, 609, 616, 626, 636, 646, 656, 666, 676, 683, 690, 699, 706, 716, 730, 737, 755, - 764, 773, 783, 793, 800, 808, 821, 829, 848, 855, - 870, 877, 884, 891, 901, 908, 915, 922, 927, 928, - 929, 929, 929, 930, 930, 930, 931, 933, 943, 952, - 959, 966, 973, 980 + 764, 773, 783, 793, 800, 808, 821, 829, 849, 856, + 871, 878, 885, 892, 902, 909, 916, 923, 928, 929, + 930, 930, 930, 931, 931, 931, 932, 934, 944, 953, + 960, 967, 974, 981 }; #endif @@ -2701,6 +2701,7 @@ yyreduce: if(!cfg_strlist_insert(&cfg_parser->cfg-> local_zones_nodefault, (yyvsp[(2) - (3)].str))) fatal_exit("out of memory adding local-zone"); + free((yyvsp[(3) - (3)].str)); } else { if(!cfg_str2list_insert(&cfg_parser->cfg->local_zones, (yyvsp[(2) - (3)].str), (yyvsp[(3) - (3)].str))) @@ -2710,7 +2711,7 @@ yyreduce: break; case 168: -#line 849 "util/configparser.y" +#line 850 "util/configparser.y" { OUTYY(("P(server_local_data:%s)\n", (yyvsp[(2) - (2)].str))); if(!cfg_strlist_insert(&cfg_parser->cfg->local_data, (yyvsp[(2) - (2)].str))) @@ -2719,7 +2720,7 @@ yyreduce: break; case 169: -#line 856 "util/configparser.y" +#line 857 "util/configparser.y" { char* ptr; OUTYY(("P(server_local_data_ptr:%s)\n", (yyvsp[(2) - (2)].str))); @@ -2736,7 +2737,7 @@ yyreduce: break; case 170: -#line 871 "util/configparser.y" +#line 872 "util/configparser.y" { OUTYY(("P(name:%s)\n", (yyvsp[(2) - (2)].str))); free(cfg_parser->cfg->stubs->name); @@ -2745,7 +2746,7 @@ yyreduce: break; case 171: -#line 878 "util/configparser.y" +#line 879 "util/configparser.y" { OUTYY(("P(stub-host:%s)\n", (yyvsp[(2) - (2)].str))); if(!cfg_strlist_insert(&cfg_parser->cfg->stubs->hosts, (yyvsp[(2) - (2)].str))) @@ -2754,7 +2755,7 @@ yyreduce: break; case 172: -#line 885 "util/configparser.y" +#line 886 "util/configparser.y" { OUTYY(("P(stub-addr:%s)\n", (yyvsp[(2) - (2)].str))); if(!cfg_strlist_insert(&cfg_parser->cfg->stubs->addrs, (yyvsp[(2) - (2)].str))) @@ -2763,7 +2764,7 @@ yyreduce: break; case 173: -#line 892 "util/configparser.y" +#line 893 "util/configparser.y" { OUTYY(("P(stub-prime:%s)\n", (yyvsp[(2) - (2)].str))); if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) @@ -2775,7 +2776,7 @@ yyreduce: break; case 174: -#line 902 "util/configparser.y" +#line 903 "util/configparser.y" { OUTYY(("P(name:%s)\n", (yyvsp[(2) - (2)].str))); free(cfg_parser->cfg->forwards->name); @@ -2784,7 +2785,7 @@ yyreduce: break; case 175: -#line 909 "util/configparser.y" +#line 910 "util/configparser.y" { OUTYY(("P(forward-host:%s)\n", (yyvsp[(2) - (2)].str))); if(!cfg_strlist_insert(&cfg_parser->cfg->forwards->hosts, (yyvsp[(2) - (2)].str))) @@ -2793,7 +2794,7 @@ yyreduce: break; case 176: -#line 916 "util/configparser.y" +#line 917 "util/configparser.y" { OUTYY(("P(forward-addr:%s)\n", (yyvsp[(2) - (2)].str))); if(!cfg_strlist_insert(&cfg_parser->cfg->forwards->addrs, (yyvsp[(2) - (2)].str))) @@ -2802,14 +2803,14 @@ yyreduce: break; case 177: -#line 923 "util/configparser.y" +#line 924 "util/configparser.y" { OUTYY(("\nP(remote-control:)\n")); } break; case 187: -#line 934 "util/configparser.y" +#line 935 "util/configparser.y" { OUTYY(("P(control_enable:%s)\n", (yyvsp[(2) - (2)].str))); if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) @@ -2821,7 +2822,7 @@ yyreduce: break; case 188: -#line 944 "util/configparser.y" +#line 945 "util/configparser.y" { OUTYY(("P(control_port:%s)\n", (yyvsp[(2) - (2)].str))); if(atoi((yyvsp[(2) - (2)].str)) == 0) @@ -2832,7 +2833,7 @@ yyreduce: break; case 189: -#line 953 "util/configparser.y" +#line 954 "util/configparser.y" { OUTYY(("P(control_interface:%s)\n", (yyvsp[(2) - (2)].str))); if(!cfg_strlist_insert(&cfg_parser->cfg->control_ifs, (yyvsp[(2) - (2)].str))) @@ -2841,7 +2842,7 @@ yyreduce: break; case 190: -#line 960 "util/configparser.y" +#line 961 "util/configparser.y" { OUTYY(("P(rc_server_key_file:%s)\n", (yyvsp[(2) - (2)].str))); free(cfg_parser->cfg->server_key_file); @@ -2850,7 +2851,7 @@ yyreduce: break; case 191: -#line 967 "util/configparser.y" +#line 968 "util/configparser.y" { OUTYY(("P(rc_server_cert_file:%s)\n", (yyvsp[(2) - (2)].str))); free(cfg_parser->cfg->server_cert_file); @@ -2859,7 +2860,7 @@ yyreduce: break; case 192: -#line 974 "util/configparser.y" +#line 975 "util/configparser.y" { OUTYY(("P(rc_control_key_file:%s)\n", (yyvsp[(2) - (2)].str))); free(cfg_parser->cfg->control_key_file); @@ -2868,7 +2869,7 @@ yyreduce: break; case 193: -#line 981 "util/configparser.y" +#line 982 "util/configparser.y" { OUTYY(("P(rc_control_cert_file:%s)\n", (yyvsp[(2) - (2)].str))); free(cfg_parser->cfg->control_cert_file); @@ -2878,7 +2879,7 @@ yyreduce: /* Line 1267 of yacc.c. */ -#line 2882 "util/configparser.c" +#line 2883 "util/configparser.c" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); @@ -3092,7 +3093,7 @@ yyreturn: } -#line 987 "util/configparser.y" +#line 988 "util/configparser.y" /* parse helper routines could be here */ diff --git a/util/configparser.y b/util/configparser.y index e150d0a75..767a4b419 100644 --- a/util/configparser.y +++ b/util/configparser.y @@ -838,6 +838,7 @@ server_local_zone: VAR_LOCAL_ZONE STRING STRING if(!cfg_strlist_insert(&cfg_parser->cfg-> local_zones_nodefault, $2)) fatal_exit("out of memory adding local-zone"); + free($3); } else { if(!cfg_str2list_insert(&cfg_parser->cfg->local_zones, $2, $3)) diff --git a/util/data/msgencode.c b/util/data/msgencode.c index 75e199d93..620c73b50 100644 --- a/util/data/msgencode.c +++ b/util/data/msgencode.c @@ -586,7 +586,9 @@ insert_query(struct query_info* qinfo, struct compress_tree_node** tree, dname_count_labels(qinfo->qname), ldns_buffer_position(buffer), region, NULL, tree)) return RETVAL_OUTMEM; - ldns_buffer_write(buffer, qinfo->qname, qinfo->qname_len); + if(ldns_buffer_current(buffer) == qinfo->qname) + ldns_buffer_skip(buffer, qinfo->qname_len); + else ldns_buffer_write(buffer, qinfo->qname, qinfo->qname_len); ldns_buffer_write_u16(buffer, qinfo->qtype); ldns_buffer_write_u16(buffer, qinfo->qclass); return RETVAL_OK; @@ -782,7 +784,9 @@ error_encode(ldns_buffer* buf, int r, struct query_info* qinfo, ldns_buffer_write(buf, &flags, sizeof(uint16_t)); ldns_buffer_write(buf, &flags, sizeof(uint16_t)); if(qinfo) { - ldns_buffer_write(buf, qinfo->qname, qinfo->qname_len); + if(ldns_buffer_current(buf) == qinfo->qname) + ldns_buffer_skip(buf, qinfo->qname_len); + else ldns_buffer_write(buf, qinfo->qname, qinfo->qname_len); ldns_buffer_write_u16(buf, qinfo->qtype); ldns_buffer_write_u16(buf, qinfo->qclass); } diff --git a/validator/val_kentry.c b/validator/val_kentry.c index 8ba7e1e0b..27bf7f286 100644 --- a/validator/val_kentry.c +++ b/validator/val_kentry.c @@ -77,6 +77,7 @@ key_entry_delkeyfunc(void* key, void* ATTR_UNUSED(userarg)) struct key_entry_key* kk = (struct key_entry_key*)key; if(!key) return; + lock_rw_destroy(&kk->entry.lock); free(kk->name); free(kk); } diff --git a/validator/val_neg.c b/validator/val_neg.c index 2d96e7574..22eeef911 100644 --- a/validator/val_neg.c +++ b/validator/val_neg.c @@ -117,6 +117,7 @@ neg_clear_zones(rbnode_t* n, void* ATTR_UNUSED(arg)) struct val_neg_zone* z = (struct val_neg_zone*)n; /* delete all the rrset entries in the tree */ traverse_postorder(&z->tree, &neg_clear_datas, NULL); + free(z->nsec3_salt); free(z->name); free(z); }