[9.18] fix: usr: Dig +yaml was producing unexpected and/or invalid YAML output

Closes #4796

Backport of MR !9127

Merge branch 'backport-4796-yaml-stringify-question-and-records-9.18' into 'bind-9.18'

See merge request isc-projects/bind9!9214
This commit is contained in:
Mark Andrews
2024-08-01 04:34:57 +00:00
4 changed files with 153 additions and 20 deletions

View File

@@ -49,3 +49,42 @@ hours 10800 A 10.53.0.2
minutes 2700 A 10.53.0.2
;TTL of 45 seconds
seconds 45 A 10.53.0.2
; domain names with yaml special values and data with ': '
yaml TXT "a: b"
'.yaml TXT "a: b"
[.yaml TXT "a: b"
{.yaml TXT "a: b"
&.yaml TXT "a: b"
#.yaml TXT "a: b"
all.yaml TXT ( \000 \001 \002 \003 \004 \005 \006 \007
\008 \009 \010 \011 \012 \013 \014 \015
\016 \017 \018 \019 \020 \021 \022 \023
\024 \025 \026 \027 \028 \029 \030 \031
\032 \033 \034 \035 \036 \037 \038 \039
\040 \041 \042 \043 \044 \045 \046 \047
\048 \049 \050 \051 \052 \053 \054 \055
\056 \057 \058 \059 \060 \061 \062 \063
\064 \065 \066 \067 \068 \069 \070 \071
\072 \073 \074 \075 \076 \077 \078 \079
\080 \081 \082 \083 \084 \085 \086 \087
\088 \089 \090 \091 \092 \093 \094 \095
\096 \097 \098 \099 \100 \101 \102 \103
\104 \105 \106 \107 \108 \109 \110 \111
\112 \113 \114 \115 \116 \117 \118 \119
\120 \121 \122 \123 \124 \125 \126 \127
\128 \129 \130 \131 \132 \133 \134 \135
\136 \137 \138 \139 \140 \141 \142 \143
\144 \145 \146 \147 \148 \149 \150 \151
\152 \153 \154 \155 \156 \157 \158 \159
\160 \161 \162 \163 \164 \165 \166 \167
\168 \169 \170 \171 \172 \173 \174 \175
\176 \177 \178 \179 \180 \181 \182 \183
\184 \185 \186 \187 \188 \189 \190 \191
\192 \193 \194 \195 \196 \197 \198 \199
\200 \201 \202 \203 \204 \205 \206 \207
\208 \209 \210 \211 \212 \213 \214 \215
\216 \217 \218 \219 \220 \221 \222 \223
\224 \225 \226 \227 \228 \229 \230 \231
\232 \233 \234 \235 \236 \237 \238 \239
\240 \241 \242 \243 \244 \245 \246 \247
\248 \249 \250 \251 \252 \253 \254 \255 )

View File

@@ -1407,5 +1407,60 @@ else
echo_i "$DELV is needed, so skipping these delv tests"
fi
if [ $HAS_PYYAML -ne 0 ]; then
for qname in "yaml" "'.yaml" "[.yaml" "{.yaml" "&.yaml" "#.yaml"; do
n=$((n + 1))
echo_i "check yaml special '${yaml}.example' ($n)"
ret=0
dig_with_opts @10.53.0.3 +yaml "${qname}.example" TXT +qr >dig.out.test$n 2>&1 || ret=1
$PYTHON yamlget.py dig.out.test$n 0 message query_message_data QUESTION_SECTION 0 >yamlget.out.test$n 2>&1 || ret=1
read -r value <yamlget.out.test$n
[ "$value" = "${qname}.example. IN TXT" ] || ret=1
$PYTHON yamlget.py dig.out.test$n 1 message response_message_data ANSWER_SECTION 0 >yamlget.out.test$n 2>&1 || ret=1
read -r value <yamlget.out.test$n
[ "$value" = "${qname}"'.example. 300 IN TXT "a: b"' ] || ret=1
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status + ret))
done
n=$((n + 1))
echo_i "check yaml character values ($n)"
ret=0
dig_with_opts @10.53.0.3 +yaml "all.yaml.example" TXT +qr >dig.out.test$n 2>&1 || ret=1
$PYTHON yamlget.py dig.out.test$n 1 message response_message_data ANSWER_SECTION 0 >yamlget.out.test$n 2>&1 || ret=1
read -r value <yamlget.out.test$n
expected='all.yaml.example. 300 IN TXT'
expected="$expected "'"\000" "\001" "\002" "\003" "\004" "\005" "\006" "\007"'
expected="$expected "'"\008" "\009" "\010" "\011" "\012" "\013" "\014" "\015"'
expected="$expected "'"\016" "\017" "\018" "\019" "\020" "\021" "\022" "\023"'
expected="$expected "'"\024" "\025" "\026" "\027" "\028" "\029" "\030" "\031"'
expected="$expected "'" " "!" "\"" "#" "$" "%" "&" "'"'"'" "(" ")" "*" "+" ","'
expected="$expected "'"-" "." "/" "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" ":"'
expected="$expected "'";" "<" "=" ">" "?" "@" "A" "B" "C" "D" "E" "F" "G" "H"'
expected="$expected "'"I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S" "T" "U" "V"'
expected="$expected "'"W" "X" "Y" "Z" "[" "\\" "]" "^" "_" "`" "a" "b" "c" "d"'
expected="$expected "'"e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r"'
expected="$expected "'"s" "t" "u" "v" "w" "x" "y" "z" "{" "|" "}" "~" "\127"'
expected="$expected "'"\128" "\129" "\130" "\131" "\132" "\133" "\134" "\135"'
expected="$expected "'"\136" "\137" "\138" "\139" "\140" "\141" "\142" "\143"'
expected="$expected "'"\144" "\145" "\146" "\147" "\148" "\149" "\150" "\151"'
expected="$expected "'"\152" "\153" "\154" "\155" "\156" "\157" "\158" "\159"'
expected="$expected "'"\160" "\161" "\162" "\163" "\164" "\165" "\166" "\167"'
expected="$expected "'"\168" "\169" "\170" "\171" "\172" "\173" "\174" "\175"'
expected="$expected "'"\176" "\177" "\178" "\179" "\180" "\181" "\182" "\183"'
expected="$expected "'"\184" "\185" "\186" "\187" "\188" "\189" "\190" "\191"'
expected="$expected "'"\192" "\193" "\194" "\195" "\196" "\197" "\198" "\199"'
expected="$expected "'"\200" "\201" "\202" "\203" "\204" "\205" "\206" "\207"'
expected="$expected "'"\208" "\209" "\210" "\211" "\212" "\213" "\214" "\215"'
expected="$expected "'"\216" "\217" "\218" "\219" "\220" "\221" "\222" "\223"'
expected="$expected "'"\224" "\225" "\226" "\227" "\228" "\229" "\230" "\231"'
expected="$expected "'"\232" "\233" "\234" "\235" "\236" "\237" "\238" "\239"'
expected="$expected "'"\240" "\241" "\242" "\243" "\244" "\245" "\246" "\247"'
expected="$expected "'"\248" "\249" "\250" "\251" "\252" "\253" "\254" "\255"'
[ "$value" = "$expected" ] || ret=1
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status + ret))
fi
echo_i "exit status: $status"
[ $status -eq 0 ] || exit 1

View File

@@ -475,12 +475,44 @@ str_totext(const char *source, isc_buffer_t *target) {
return (ISC_R_SUCCESS);
}
static isc_result_t
yaml_stringify(isc_buffer_t *target, char *start) {
isc_region_t r;
char *s = start;
char *tmp = NULL;
isc_buffer_availableregion(target, &r);
if (r.length < 1) {
return (ISC_R_NOSPACE);
}
/* NUL terminate buffer for string operations below */
r.base[0] = '\0';
/* Escape quotes in string using quote quote */
while ((tmp = strchr(s, '\'')) != NULL) {
isc_buffer_availableregion(target, &r);
/* Space to shift by 1 with trailing NUL? */
if (r.length < 2) {
return (ISC_R_NOSPACE);
}
memmove(tmp + 1, tmp,
(char *)isc_buffer_used(target) - tmp + 1);
isc_buffer_add(target, 1);
/* We now have "''..." - skip both quotes. */
s = tmp + 2;
}
return (ISC_R_SUCCESS);
}
static isc_result_t
ncache_summary(dns_rdataset_t *rdataset, bool omit_final_dot,
dns_totext_ctx_t *ctx, isc_buffer_t *target) {
isc_result_t result = ISC_R_SUCCESS;
dns_rdataset_t rds;
dns_name_t name;
char *start = NULL;
dns_rdataset_init(&rds);
dns_name_init(&name, NULL);
@@ -501,7 +533,8 @@ ncache_summary(dns_rdataset_t *rdataset, bool omit_final_dot,
}
if ((ctx->style.flags & DNS_STYLEFLAG_YAML) != 0) {
CHECK(str_totext("- ", target));
CHECK(str_totext("- '", target));
start = isc_buffer_used(target);
} else {
CHECK(str_totext("; ", target));
}
@@ -512,7 +545,7 @@ ncache_summary(dns_rdataset_t *rdataset, bool omit_final_dot,
if (rds.type == dns_rdatatype_rrsig) {
CHECK(str_totext(" ", target));
CHECK(dns_rdatatype_totext(rds.covers, target));
CHECK(str_totext(" ...\n", target));
CHECK(str_totext(" ...", target));
} else {
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdataset_current(&rds, &rdata);
@@ -520,8 +553,12 @@ ncache_summary(dns_rdataset_t *rdataset, bool omit_final_dot,
CHECK(dns_rdata_tofmttext(&rdata, dns_rootname,
0, 0, 0, " ",
target));
CHECK(str_totext("\n", target));
}
if (start != NULL) {
RETERR(yaml_stringify(target, start));
CHECK(str_totext("\'", target));
}
CHECK(str_totext("\n", target));
}
dns_rdataset_disassociate(&rds);
result = dns_rdataset_next(rdataset);
@@ -559,6 +596,7 @@ rdataset_totext(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
dns_fixedname_t fixed;
dns_name_t *name = NULL;
unsigned int i;
char *start = NULL;
REQUIRE(DNS_RDATASET_VALID(rdataset));
@@ -592,7 +630,8 @@ rdataset_totext(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
* YAML or comment prefix?
*/
if ((ctx->style.flags & DNS_STYLEFLAG_YAML) != 0) {
RETERR(str_totext("- ", target));
RETERR(str_totext("- '", target));
start = isc_buffer_used(target);
} else if ((ctx->style.flags & DNS_STYLEFLAG_COMMENTDATA) != 0)
{
RETERR(str_totext(";", target));
@@ -740,7 +779,6 @@ rdataset_totext(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
break;
} else {
dns_rdata_t rdata = DNS_RDATA_INIT;
isc_region_t r;
dns_rdataset_current(rdataset, &rdata);
@@ -750,13 +788,12 @@ rdataset_totext(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
ctx->style.rdata_column,
ctx->style.split_width, ctx->linebreak,
target));
isc_buffer_availableregion(target, &r);
if (r.length < 1) {
return (ISC_R_NOSPACE);
if (start != NULL) {
RETERR(yaml_stringify(target, start));
RETERR(str_totext("'\n", target));
} else {
RETERR(str_totext("\n", target));
}
r.base[0] = '\n';
isc_buffer_add(target, 1);
}
first = false;
@@ -792,7 +829,7 @@ question_totext(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
isc_buffer_t *target) {
unsigned int column;
isc_result_t result;
isc_region_t r;
char *start = NULL;
REQUIRE(DNS_RDATASET_VALID(rdataset));
result = dns_rdataset_first(rdataset);
@@ -800,6 +837,11 @@ question_totext(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
column = 0;
if ((ctx->style.flags & DNS_STYLEFLAG_YAML) != 0) {
RETERR(str_totext("- '", target));
start = isc_buffer_used(target);
}
/* Owner name */
{
unsigned int name_start = target->used;
@@ -842,12 +884,11 @@ question_totext(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
column += (target->used - type_start);
}
isc_buffer_availableregion(target, &r);
if (r.length < 1) {
return (ISC_R_NOSPACE);
if (start != NULL) {
RETERR(yaml_stringify(target, start));
RETERR(str_totext("\'", target));
}
r.base[0] = '\n';
isc_buffer_add(target, 1);
RETERR(str_totext("\n", target));
return (ISC_R_SUCCESS);
}

View File

@@ -3396,9 +3396,7 @@ dns_message_sectiontotext(dns_message_t *msg, dns_section_t section,
}
if (section == DNS_SECTION_QUESTION) {
INDENT(style);
if ((sflags & DNS_STYLEFLAG_YAML) != 0) {
ADD_STRING(target, "- ");
} else {
if ((sflags & DNS_STYLEFLAG_YAML) == 0) {
ADD_STRING(target, ";");
}
result = dns_master_questiontotext(