X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/b94ea1bd61485a97c2d0dc2cab4c4d86ffe82e89..4687a69c269ee3f2a7f0625e0147a503fd9d3d0b:/src/src/lookups/dnsdb.c diff --git a/src/src/lookups/dnsdb.c b/src/src/lookups/dnsdb.c index fcf80e3dd..af1ad9dab 100644 --- a/src/src/lookups/dnsdb.c +++ b/src/src/lookups/dnsdb.c @@ -2,7 +2,7 @@ * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) The Exim Maintainers 2020 - 2022 */ +/* Copyright (c) The Exim Maintainers 2020 - 2023 */ /* Copyright (c) University of Cambridge 1995 - 2018 */ /* See the file NOTICE for conditions of use and distribution. */ /* SPDX-License-Identifier: GPL-2.0-or-later */ @@ -154,8 +154,7 @@ gstring * yield = string_get(256); /* If the string starts with '>' we change the output separator. If it's followed by ';' or ',' we set the TXT output separator. */ -while (isspace(*keystring)) keystring++; -if (*keystring == '>') +if (Uskip_whitespace(&keystring) == '>') { outsep = keystring + 1; keystring += 2; @@ -169,7 +168,7 @@ if (*keystring == '>') outsep2 = US""; keystring++; } - while (isspace(*keystring)) keystring++; + Uskip_whitespace(&keystring); } /* Check for a modifier keyword. */ @@ -234,14 +233,14 @@ for (;;) else break; - while (isspace(*keystring)) keystring++; + Uskip_whitespace(&keystring); if (*keystring++ != ',') { *errmsg = US"dnsdb modifier syntax error"; rc = DEFER; goto out; } - while (isspace(*keystring)) keystring++; + Uskip_whitespace(&keystring); } /* Figure out the "type" value if it is not T_TXT. @@ -272,7 +271,7 @@ if ((equals = Ustrchr(keystring, '=')) != NULL) } keystring = equals + 1; - while (isspace(*keystring)) keystring++; + Uskip_whitespace(&keystring); } /* Initialize the resolver in case this is the first time it has been used. */ @@ -387,38 +386,31 @@ while ((domain = string_nextinlist(&keystring, &sep, NULL, 0))) } /* Other kinds of record just have one piece of data each, but there may be - several of them, of course. */ + several of them, of course. TXT & SPF can have data in multiple chunks. */ if (yield->ptr) yield = string_catn(yield, outsep, 1); if (type == T_TXT || type == T_SPF) - { - if (!outsep2) /* output only the first item of data */ + for (unsigned data_offset = 0; data_offset + 1 < rr->size; ) { - uschar n = (rr->data)[0]; - /* size byte + data bytes must not excced the RRs length */ - if (n + 1 <= rr->size) - yield = string_catn(yield, US (rr->data+1), n); + uschar chunk_len = (rr->data)[data_offset]; + int remain; + + if (outsep2 && *outsep2 && data_offset != 0) + yield = string_catn(yield, outsep2, 1); + + /* Apparently there are resolvers that do not check RRs before passing + them on, and glibc fails to do so. So every application must... + Check for chunk len exceeding RR */ + + remain = rr->size - ++data_offset; + if (chunk_len > remain) + chunk_len = remain; + yield = string_catn(yield, US ((rr->data) + data_offset), chunk_len); + data_offset += chunk_len; + + if (!outsep2) break; /* output only the first chunk of the RR */ } - else - for (unsigned data_offset = 0; data_offset < rr->size; ) - { - uschar chunk_len = (rr->data)[data_offset]; - int remain = rr->size - data_offset; - - /* Apparently there are resolvers that do not check RRs before passing - them on, and glibc fails to do so. So every application must... - Check for chunk len exceeding RR */ - - if (chunk_len > remain) - chunk_len = remain; - - if (*outsep2 && data_offset != 0) - yield = string_catn(yield, outsep2, 1); - yield = string_catn(yield, US ((rr->data) + ++data_offset), --chunk_len); - data_offset += chunk_len; - } - } else if (type == T_TLSA) if (rr->size < 3) continue; @@ -452,20 +444,20 @@ while ((domain = string_nextinlist(&keystring, &sep, NULL, 0))) switch (type) { case T_MXH: - if (rr_bad_size(rr, sizeof(u_int16_t))) continue; + if (rr_bad_size(rr, sizeof(uint16_t))) continue; /* mxh ignores the priority number and includes only the hostnames */ GETSHORT(priority, p); break; case T_MX: - if (rr_bad_size(rr, sizeof(u_int16_t))) continue; + if (rr_bad_size(rr, sizeof(uint16_t))) continue; GETSHORT(priority, p); sprintf(CS s, "%d%c", priority, *outsep2); yield = string_cat(yield, s); break; case T_SRV: - if (rr_bad_size(rr, 3*sizeof(u_int16_t))) continue; + if (rr_bad_size(rr, 3*sizeof(uint16_t))) continue; GETSHORT(priority, p); GETSHORT(weight, p); GETSHORT(port, p); @@ -475,7 +467,7 @@ while ((domain = string_nextinlist(&keystring, &sep, NULL, 0))) break; case T_CSA: - if (rr_bad_size(rr, 3*sizeof(u_int16_t))) continue; + if (rr_bad_size(rr, 3*sizeof(uint16_t))) continue; /* See acl_verify_csa() for more comments about CSA. */ GETSHORT(priority, p); GETSHORT(weight, p);