]>
Commit | Line | Data |
---|---|---|
1 | Adapted from https://git.exim.org/exim.git/patch/79670d3c32ccb37fe06f25d8192943b58606a32a | |
2 | ||
3 | Reference: https://bugs.exim.org/show_bug.cgi?id=3054 | |
4 | -- | |
5 | From 79670d3c32ccb37fe06f25d8192943b58606a32a Mon Sep 17 00:00:00 2001 | |
6 | From: Jeremy Harris <jgh146exb@wizmail.org> | |
7 | Date: Fri, 17 Nov 2023 16:55:17 +0000 | |
8 | Subject: [PATCH] Lookups: Fix dnsdb lookup of multi-chunk TXT. Bug 3054 | |
9 | ||
10 | Broken=by: f6b1f8e7d642 | |
11 | ||
12 | --- a/src/lookups/dnsdb.c | |
13 | +++ b/src/lookups/dnsdb.c | |
14 | @@ -387,38 +387,31 @@ while ((domain = string_nextinlist(&keystring, &sep, NULL, 0))) | |
15 | } | |
16 | ||
17 | /* Other kinds of record just have one piece of data each, but there may be | |
18 | - several of them, of course. */ | |
19 | + several of them, of course. TXT & SPF can have data in multiple chunks. */ | |
20 | ||
21 | if (yield->ptr) yield = string_catn(yield, outsep, 1); | |
22 | ||
23 | if (type == T_TXT || type == T_SPF) | |
24 | - { | |
25 | - if (!outsep2) /* output only the first item of data */ | |
26 | + for (unsigned data_offset = 0; data_offset + 1 < rr->size; ) | |
27 | { | |
28 | - uschar n = (rr->data)[0]; | |
29 | - /* size byte + data bytes must not excced the RRs length */ | |
30 | - if (n + 1 <= rr->size) | |
31 | - yield = string_catn(yield, US (rr->data+1), n); | |
32 | + uschar chunk_len = (rr->data)[data_offset]; | |
33 | + int remain; | |
34 | + | |
35 | + if (outsep2 && *outsep2 && data_offset != 0) | |
36 | + yield = string_catn(yield, outsep2, 1); | |
37 | + | |
38 | + /* Apparently there are resolvers that do not check RRs before passing | |
39 | + them on, and glibc fails to do so. So every application must... | |
40 | + Check for chunk len exceeding RR */ | |
41 | + | |
42 | + remain = rr->size - ++data_offset; | |
43 | + if (chunk_len > remain) | |
44 | + chunk_len = remain; | |
45 | + yield = string_catn(yield, US ((rr->data) + data_offset), chunk_len); | |
46 | + data_offset += chunk_len; | |
47 | + | |
48 | + if (!outsep2) break; /* output only the first chunk of the RR */ | |
49 | } | |
50 | - else | |
51 | - for (unsigned data_offset = 0; data_offset < rr->size; ) | |
52 | - { | |
53 | - uschar chunk_len = (rr->data)[data_offset]; | |
54 | - int remain = rr->size - data_offset; | |
55 | - | |
56 | - /* Apparently there are resolvers that do not check RRs before passing | |
57 | - them on, and glibc fails to do so. So every application must... | |
58 | - Check for chunk len exceeding RR */ | |
59 | - | |
60 | - if (chunk_len > remain) | |
61 | - chunk_len = remain; | |
62 | - | |
63 | - if (*outsep2 && data_offset != 0) | |
64 | - yield = string_catn(yield, outsep2, 1); | |
65 | - yield = string_catn(yield, US ((rr->data) + ++data_offset), --chunk_len); | |
66 | - data_offset += chunk_len; | |
67 | - } | |
68 | - } | |
69 | else if (type == T_TLSA) | |
70 | if (rr->size < 3) | |
71 | continue; |