From: Mark Andrews Date: Mon, 18 Nov 2019 09:46:58 +0000 (+1100) Subject: dns_master_indent and dns_master_indentstr must not be global X-Git-Tag: v9.15.7~63^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9936462f31a6a19447794ea460b20a9d1c8b49e0;p=thirdparty%2Fbind9.git dns_master_indent and dns_master_indentstr must not be global The indentation for dumping the master zone was driven by two global variables dns_master_indent and dns_master_indentstr. In threaded mode, this becomes prone to data access races, so this commit converts the global variables into a local per-context tuple that consist of count and string. --- diff --git a/bin/delv/delv.c b/bin/delv/delv.c index d62b8f7a137..153165b1e0b 100644 --- a/bin/delv/delv.c +++ b/bin/delv/delv.c @@ -498,14 +498,17 @@ printdata(dns_rdataset_t *rdataset, dns_name_t *owner, dns_rdata_reset(&rdata); } } else { + dns_indent_t indent = { " ", 2 }; if (!yaml && (rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) { isc_buffer_putstr(&target, "; "); } - result = dns_master_rdatasettotext(owner, rdataset, - style, &target); + style, + yaml ? &indent : + NULL, + &target); } if (result == ISC_R_NOSPACE) { @@ -537,8 +540,6 @@ setup_style(dns_master_style_t **stylep) { styleflags |= DNS_STYLEFLAG_REL_OWNER; if (yaml) { styleflags |= DNS_STYLEFLAG_YAML; - dns_master_indentstr = " "; - dns_master_indent = 2; } else { if (showcomments) { styleflags |= DNS_STYLEFLAG_COMMENT; diff --git a/bin/dig/dig.c b/bin/dig/dig.c index e8541aea643..daaf486534a 100644 --- a/bin/dig/dig.c +++ b/bin/dig/dig.c @@ -487,8 +487,8 @@ printmessage(dig_query_t *query, const isc_buffer_t *msgbuf, styleflags |= DNS_STYLEFLAG_REL_OWNER; if (yaml) { - dns_master_indentstr = " "; - dns_master_indent = 3; + msg->indent.string = " "; + msg->indent.count = 3; styleflags |= DNS_STYLEFLAG_YAML; } else { if (query->lookup->comments) { diff --git a/bin/dnssec/dnssec-cds.c b/bin/dnssec/dnssec-cds.c index 9b362630fa8..8796bc078af 100644 --- a/bin/dnssec/dnssec-cds.c +++ b/bin/dnssec/dnssec-cds.c @@ -372,7 +372,7 @@ formatset(dns_rdataset_t *rdataset) { result = isc_buffer_allocate(mctx, &buf, MAX_CDS_RDATA_TEXT_SIZE); check_result(result, "printing DS records"); - result = dns_master_rdatasettotext(name, rdataset, style, buf); + result = dns_master_rdatasettotext(name, rdataset, style, NULL, buf); if ((result == ISC_R_SUCCESS) && isc_buffer_availablelength(buf) < 1) { result = ISC_R_NOSPACE; diff --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c index ff87a48469a..7682a178e9e 100644 --- a/bin/dnssec/dnssec-signzone.c +++ b/bin/dnssec/dnssec-signzone.c @@ -246,7 +246,8 @@ dumpnode(dns_name_t *name, dns_dbnode_t *node) { for (;;) { result = dns_master_rdatasettotext(name, &rds, - masterstyle, buffer); + masterstyle, NULL, + buffer); if (result != ISC_R_NOSPACE) break; diff --git a/bin/tests/system/digdelv/tests.sh b/bin/tests/system/digdelv/tests.sh index 8736f66dec8..ff786f44b7f 100644 --- a/bin/tests/system/digdelv/tests.sh +++ b/bin/tests/system/digdelv/tests.sh @@ -752,6 +752,7 @@ if [ -x "$DIG" ] ; then status=$((status+ret)) fi + n=$((n+1)) echo_i "check that dig +unexpected works ($n)" ret=0 dig_with_opts @10.53.0.6 +unexpected a a.example > dig.out.test$n || ret=1 diff --git a/bin/tools/dnstap-read.c b/bin/tools/dnstap-read.c index 77d964074b4..4a6cca1d901 100644 --- a/bin/tools/dnstap-read.c +++ b/bin/tools/dnstap-read.c @@ -291,6 +291,8 @@ print_yaml(dns_dtdata_t *dt) { } if (dt->msg != NULL) { + dt->msg->indent.count = 2; + dt->msg->indent.string = " "; printf(" %s:\n", ((dt->type & DNS_DTTYPE_QUERY) != 0) ? "query_message_data" : "response_message_data"); @@ -327,8 +329,6 @@ main(int argc, char *argv[]) { break; case 'y': yaml = true; - dns_master_indentstr = " "; - dns_master_indent = 2; break; default: usage(); diff --git a/bin/tools/mdig.c b/bin/tools/mdig.c index bf889228e4a..c8a2494256b 100644 --- a/bin/tools/mdig.c +++ b/bin/tools/mdig.c @@ -248,9 +248,9 @@ recvresponse(isc_task_t *task, isc_event_t *event) { styleflags |= DNS_STYLEFLAG_REL_OWNER; if (yaml) { - dns_master_indentstr = " "; - dns_master_indent = 3; styleflags |= DNS_STYLEFLAG_YAML; + response->indent.string = " "; + response->indent.count = 3; } else { if (display_comments) { styleflags |= DNS_STYLEFLAG_COMMENT; diff --git a/lib/dns/include/dns/masterdump.h b/lib/dns/include/dns/masterdump.h index 28bc5564939..2cdeddc1666 100644 --- a/lib/dns/include/dns/masterdump.h +++ b/lib/dns/include/dns/masterdump.h @@ -165,8 +165,7 @@ LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_debug; LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_comment; /*% - * Similar to dns_master_style_debug but data is indented with - * dns_master_indentstr (defaults to tab). + * Similar to dns_master_style_debug but data is indented with "\t" (tab) */ LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_indent; @@ -180,27 +179,6 @@ LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_keyzone; */ LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_yaml; -/*% - * The default indent string to prepend lines with when using - * styleflag DNS_STYLEFLAG_INDENT or DNS_STYLEFLAG_YAML. - * This is set to "\t" by default. The indent is repeated - * 'dns_master_indent' times. This precedes everything else - * on the line, including comment characters (;). - * - * XXX: Changing this value at runtime is not thread-safe. - */ -LIBDNS_EXTERNAL_DATA extern const char *dns_master_indentstr; - -/*% - * The number of copies of the indent string to put at the beginning - * of the line when using DNS_STYLEFLAG_INDENT or DNS_STYLEFLAG_YAML. - * This is set to 1 by default. It is increased and decreased - * to adjust indentation levels when producing YAML output. - * - * XXX: This is not thread-safe. - */ -LIBDNS_EXTERNAL_DATA extern unsigned int dns_master_indent; - /*** *** Functions ***/ @@ -341,7 +319,7 @@ isc_result_t dns_master_rdatasettotext(const dns_name_t *owner_name, dns_rdataset_t *rdataset, const dns_master_style_t *style, - isc_buffer_t *target); + dns_indent_t *indent, isc_buffer_t *target); /*%< * Convert 'rdataset' to text format, storing the result in 'target'. * diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h index e0f0aa365ad..fcacbd43dbd 100644 --- a/lib/dns/include/dns/message.h +++ b/lib/dns/include/dns/message.h @@ -269,6 +269,8 @@ struct dns_message { dns_rdatasetorderfunc_t order; dns_sortlist_arg_t order_arg; + + dns_indent_t indent; }; struct dns_ednsopt { diff --git a/lib/dns/include/dns/types.h b/lib/dns/include/dns/types.h index 728fb0c0a1f..68f60c2061e 100644 --- a/lib/dns/include/dns/types.h +++ b/lib/dns/include/dns/types.h @@ -388,6 +388,11 @@ typedef enum { dns_stale_answer_conf } dns_stale_answer_t; +typedef struct { + const char *string; + size_t count; +} dns_indent_t; + /* * Functions. */ diff --git a/lib/dns/masterdump.c b/lib/dns/masterdump.c index 1e5606e7209..309beddf7b0 100644 --- a/lib/dns/masterdump.c +++ b/lib/dns/masterdump.c @@ -98,6 +98,7 @@ typedef struct dns_totext_ctx { uint32_t current_ttl; bool current_ttl_valid; dns_ttl_t serve_stale_ttl; + dns_indent_t indent; } dns_totext_ctx_t; LIBDNS_EXTERNAL_DATA const dns_master_style_t @@ -175,7 +176,7 @@ dns_master_style_debug = { }; /*% - * Similar, but indented (i.e., prepended with dns_master_indentstr). + * Similar, but indented (i.e., prepended with msg->indent.string). */ LIBDNS_EXTERNAL_DATA const dns_master_style_t dns_master_style_indent = { @@ -207,12 +208,6 @@ dns_master_style_yaml = { 24, 32, 40, 48, 80, 8, UINT_MAX }; -/*% - * Default indent string. - */ -LIBDNS_EXTERNAL_DATA const char *dns_master_indentstr = "\t"; -LIBDNS_EXTERNAL_DATA unsigned int dns_master_indent = 1; - #define N_SPACES 10 static char spaces[N_SPACES+1] = " "; @@ -251,6 +246,8 @@ struct dns_dumpctx { #define NXDOMAIN(x) (((x)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0) +static const dns_indent_t default_indent = { "\t", 1 }; + /*% * Output tabs and spaces to go from column '*current' to * column 'to', and update '*current' to reflect the new @@ -317,7 +314,9 @@ indent(unsigned int *current, unsigned int to, int tabwidth, } static isc_result_t -totext_ctx_init(const dns_master_style_t *style, dns_totext_ctx_t *ctx) { +totext_ctx_init(const dns_master_style_t *style, const dns_indent_t *indentctx, + dns_totext_ctx_t *ctx) +{ isc_result_t result; REQUIRE(style->tab_width != 0); @@ -347,11 +346,14 @@ totext_ctx_init(const dns_master_style_t *style, dns_totext_ctx_t *ctx) { if ((ctx->style.flags & DNS_STYLEFLAG_INDENT) != 0 || (ctx->style.flags & DNS_STYLEFLAG_YAML) != 0) { - unsigned int i, len = strlen(dns_master_indentstr); - for (i = 0; i < dns_master_indent; i++) { + if (indentctx == NULL) { + indentctx = &default_indent; + } + unsigned int i, len = strlen(indentctx->string); + for (i = 0; i < indentctx->count; i++) { if (isc_buffer_availablelength(&buf) < len) return (DNS_R_TEXTTOOLONG); - isc_buffer_putstr(&buf, dns_master_indentstr); + isc_buffer_putstr(&buf, indentctx->string); } } @@ -392,6 +394,7 @@ totext_ctx_init(const dns_master_style_t *style, dns_totext_ctx_t *ctx) { ctx->current_ttl = 0; ctx->current_ttl_valid = false; ctx->serve_stale_ttl = 0; + ctx->indent = indentctx ? *indentctx : default_indent; return (ISC_R_SUCCESS); } @@ -445,8 +448,8 @@ ncache_summary(dns_rdataset_t *rdataset, bool omit_final_dot, (ctx->style.flags & DNS_STYLEFLAG_YAML) != 0) { unsigned int i; - for (i = 0; i < dns_master_indent; i++) { - CHECK(str_totext(dns_master_indentstr, + for (i = 0; i < ctx->indent.count; i++) { + CHECK(str_totext(ctx->indent.string, target)); } } @@ -534,8 +537,8 @@ rdataset_totext(dns_rdataset_t *rdataset, if ((ctx->style.flags & DNS_STYLEFLAG_INDENT) != 0 || (ctx->style.flags & DNS_STYLEFLAG_YAML) != 0) { - for (i = 0; i < dns_master_indent; i++) - RETERR(str_totext(dns_master_indentstr, + for (i = 0; i < ctx->indent.count; i++) + RETERR(str_totext(ctx->indent.string, target)); } @@ -801,7 +804,7 @@ dns_rdataset_totext(dns_rdataset_t *rdataset, { dns_totext_ctx_t ctx; isc_result_t result; - result = totext_ctx_init(&dns_master_style_debug, &ctx); + result = totext_ctx_init(&dns_master_style_debug, NULL, &ctx); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "could not set master file style"); @@ -829,11 +832,11 @@ isc_result_t dns_master_rdatasettotext(const dns_name_t *owner_name, dns_rdataset_t *rdataset, const dns_master_style_t *style, - isc_buffer_t *target) + dns_indent_t *indent, isc_buffer_t *target) { dns_totext_ctx_t ctx; isc_result_t result; - result = totext_ctx_init(style, &ctx); + result = totext_ctx_init(style, indent, &ctx); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "could not set master file style"); @@ -852,7 +855,7 @@ dns_master_questiontotext(const dns_name_t *owner_name, { dns_totext_ctx_t ctx; isc_result_t result; - result = totext_ctx_init(style, &ctx); + result = totext_ctx_init(style, NULL, &ctx); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "could not set master file style"); @@ -1039,8 +1042,8 @@ dump_rdatasets_text(isc_mem_t *mctx, const dns_name_t *name, (ctx->style.flags & DNS_STYLEFLAG_YAML) != 0) { unsigned int j; - for (j = 0; j < dns_master_indent; j++) - fprintf(f, "%s", dns_master_indentstr); + for (j = 0; j < ctx->indent.count; j++) + fprintf(f, "%s", ctx->indent.string); } fprintf(f, "; %s\n", dns_trust_totext(rds->trust)); } @@ -1072,8 +1075,8 @@ dump_rdatasets_text(isc_mem_t *mctx, const dns_name_t *name, (ctx->style.flags & DNS_STYLEFLAG_YAML) != 0) { unsigned int j; - for (j = 0; j < dns_master_indent; j++) - fprintf(f, "%s", dns_master_indentstr); + for (j = 0; j < ctx->indent.count; j++) + fprintf(f, "%s", ctx->indent.string); } fprintf(f, "; resign=%s\n", buf); } @@ -1493,7 +1496,7 @@ dumpctx_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, ISC_UNREACHABLE(); } - result = totext_ctx_init(style, &dctx->tctx); + result = totext_ctx_init(style, NULL, &dctx->tctx); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "could not set master file style"); @@ -1935,7 +1938,7 @@ dns_master_dumpnodetostream(isc_mem_t *mctx, dns_db_t *db, dns_totext_ctx_t ctx; dns_rdatasetiter_t *rdsiter = NULL; - result = totext_ctx_init(style, &ctx); + result = totext_ctx_init(style, NULL, &ctx); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "could not set master file style"); diff --git a/lib/dns/message.c b/lib/dns/message.c index 31321b86444..282357c770a 100644 --- a/lib/dns/message.c +++ b/lib/dns/message.c @@ -428,6 +428,8 @@ msginit(dns_message_t *m) { m->tkey = 0; m->rdclass_set = 0; m->querytsig = NULL; + m->indent.string = "\t"; + m->indent.count = 0; } static inline void @@ -3259,8 +3261,8 @@ dns_message_checksig(dns_message_t *msg, dns_view_t *view) { if ((__flags & DNS_STYLEFLAG_INDENT) == 0ULL && \ (__flags & DNS_STYLEFLAG_YAML) == 0ULL) \ break; \ - for (__i = 0; __i < dns_master_indent; __i++) { \ - ADD_STRING(target, dns_master_indentstr); \ + for (__i = 0; __i < msg->indent.count; __i++) { \ + ADD_STRING(target, msg->indent.string); \ } \ } while (0) @@ -3268,23 +3270,26 @@ isc_result_t dns_message_sectiontotext(dns_message_t *msg, dns_section_t section, const dns_master_style_t *style, dns_messagetextflag_t flags, - isc_buffer_t *target) { + isc_buffer_t *target) +{ dns_name_t *name, empty_name; dns_rdataset_t *rdataset; isc_result_t result = ISC_R_SUCCESS; bool seensoa = false; - unsigned int saveindent; + size_t saved_count; dns_masterstyle_flags_t sflags; REQUIRE(DNS_MESSAGE_VALID(msg)); REQUIRE(target != NULL); REQUIRE(VALID_SECTION(section)); - saveindent = dns_master_indent; - sflags = dns_master_styleflags(style); - if (ISC_LIST_EMPTY(msg->sections[section])) + saved_count = msg->indent.count; + + if (ISC_LIST_EMPTY(msg->sections[section])) { goto cleanup; + } + sflags = dns_master_styleflags(style); INDENT(style); if ((sflags & DNS_STYLEFLAG_YAML) != 0) { @@ -3310,7 +3315,7 @@ dns_message_sectiontotext(dns_message_t *msg, dns_section_t section, goto cleanup; } if ((sflags & DNS_STYLEFLAG_YAML) != 0) { - dns_master_indent++; + msg->indent.count++; } do { name = NULL; @@ -3342,6 +3347,7 @@ dns_message_sectiontotext(dns_message_t *msg, dns_section_t section, result = dns_master_rdatasettotext(name, rdataset, style, + &msg->indent, target); } if (result != ISC_R_SUCCESS) @@ -3350,7 +3356,7 @@ dns_message_sectiontotext(dns_message_t *msg, dns_section_t section, result = dns_message_nextname(msg, section); } while (result == ISC_R_SUCCESS); if ((sflags & DNS_STYLEFLAG_YAML) != 0) { - dns_master_indent--; + msg->indent.count--; } if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 && (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0 && @@ -3363,7 +3369,7 @@ dns_message_sectiontotext(dns_message_t *msg, dns_section_t section, result = ISC_R_SUCCESS; cleanup: - dns_master_indent = saveindent; + msg->indent.count = saved_count; return (result); } @@ -3479,13 +3485,15 @@ dns_message_pseudosectiontoyaml(dns_message_t *msg, dns_rdata_t rdata; isc_buffer_t optbuf; uint16_t optcode, optlen; + size_t saved_count; unsigned char *optdata; - unsigned int saveindent = dns_master_indent; REQUIRE(DNS_MESSAGE_VALID(msg)); REQUIRE(target != NULL); REQUIRE(VALID_PSEUDOSECTION(section)); + saved_count = msg->indent.count; + switch (section) { case DNS_PSEUDOSECTION_OPT: ps = dns_message_getopt(msg); @@ -3495,11 +3503,11 @@ dns_message_pseudosectiontoyaml(dns_message_t *msg, INDENT(style); ADD_STRING(target, "OPT_PSEUDOSECTION:\n"); - dns_master_indent++; + msg->indent.count++; INDENT(style); ADD_STRING(target, "EDNS:\n"); - dns_master_indent++; + msg->indent.count++; INDENT(style); ADD_STRING(target, "version: "); @@ -3747,7 +3755,8 @@ dns_message_pseudosectiontoyaml(dns_message_t *msg, } INDENT(style); ADD_STRING(target, "TSIG_PSEUDOSECTION:\n"); - result = dns_master_rdatasettotext(name, ps, style, target); + result = dns_master_rdatasettotext(name, ps, style, + &msg->indent, target); ADD_STRING(target, "\n"); goto cleanup; case DNS_PSEUDOSECTION_SIG0: @@ -3758,7 +3767,8 @@ dns_message_pseudosectiontoyaml(dns_message_t *msg, } INDENT(style); ADD_STRING(target, "SIG0_PSEUDOSECTION:\n"); - result = dns_master_rdatasettotext(name, ps, style, target); + result = dns_master_rdatasettotext(name, ps, style, + &msg->indent, target); if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 && (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) ADD_STRING(target, "\n"); @@ -3768,7 +3778,7 @@ dns_message_pseudosectiontoyaml(dns_message_t *msg, result = ISC_R_UNEXPECTED; cleanup: - dns_master_indent = saveindent; + msg->indent.count = saved_count; return (result); } @@ -3793,9 +3803,11 @@ dns_message_pseudosectiontotext(dns_message_t *msg, REQUIRE(target != NULL); REQUIRE(VALID_PSEUDOSECTION(section)); - if ((dns_master_styleflags(style) & DNS_STYLEFLAG_YAML) != 0) + if ((dns_master_styleflags(style) & DNS_STYLEFLAG_YAML) != 0) { return (dns_message_pseudosectiontoyaml(msg, section, style, flags, target)); + } + switch (section) { case DNS_PSEUDOSECTION_OPT: ps = dns_message_getopt(msg); @@ -4039,7 +4051,8 @@ dns_message_pseudosectiontotext(dns_message_t *msg, INDENT(style); if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) ADD_STRING(target, ";; TSIG PSEUDOSECTION:\n"); - result = dns_master_rdatasettotext(name, ps, style, target); + result = dns_master_rdatasettotext(name, ps, style, + &msg->indent, target); if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 && (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) ADD_STRING(target, "\n"); @@ -4051,7 +4064,8 @@ dns_message_pseudosectiontotext(dns_message_t *msg, INDENT(style); if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) ADD_STRING(target, ";; SIG0 PSEUDOSECTION:\n"); - result = dns_master_rdatasettotext(name, ps, style, target); + result = dns_master_rdatasettotext(name, ps, style, + &msg->indent, target); if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 && (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) ADD_STRING(target, "\n"); diff --git a/lib/dns/sdlz.c b/lib/dns/sdlz.c index 8d6b3088747..c7b2062d64c 100644 --- a/lib/dns/sdlz.c +++ b/lib/dns/sdlz.c @@ -1086,7 +1086,7 @@ modrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, goto cleanup; result = dns_master_rdatasettotext(sdlznode->name, rdataset, - style, buffer); + style, NULL, buffer); if (result != ISC_R_SUCCESS) goto cleanup; diff --git a/lib/dns/tests/master_test.c b/lib/dns/tests/master_test.c index df4d078abaa..cc93da0a458 100644 --- a/lib/dns/tests/master_test.c +++ b/lib/dns/tests/master_test.c @@ -429,8 +429,8 @@ totext_test(void **state) { assert_int_equal(result, ISC_R_SUCCESS); isc_buffer_init(&target, buf, BIGBUFLEN); - result = dns_master_rdatasettotext(dns_rootname, - &rdataset, &dns_master_style_debug, + result = dns_master_rdatasettotext(dns_rootname, &rdataset, + &dns_master_style_debug, NULL, &target); assert_int_equal(result, ISC_R_SUCCESS); assert_int_equal(isc_buffer_usedlength(&target), 0);