From 63deec8a3ba77fcabf405d9c30fdd65a8b909526 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Sun, 5 Feb 2023 16:04:14 +0000 Subject: More abstraction of the gstring API --- src/src/acl.c | 2 +- src/src/arc.c | 26 ++++----- src/src/deliver.c | 44 ++++++++------- src/src/dkim.c | 6 +- src/src/exim.c | 12 ++-- src/src/expand.c | 143 ++++++++++++++++++++++++++---------------------- src/src/functions.h | 53 ++++++++++++++++++ src/src/imap_utf7.c | 4 +- src/src/log.c | 20 ++++--- src/src/lookups/dnsdb.c | 30 ++++------ src/src/lookups/ldap.c | 18 +++--- src/src/mime.c | 2 +- src/src/parse.c | 12 ++-- src/src/pdkim/pdkim.c | 5 +- src/src/readconf.c | 2 +- src/src/receive.c | 5 +- src/src/rfc2047.c | 27 ++++----- src/src/sieve.c | 31 ++++------- src/src/smtp_in.c | 38 +++++++------ src/src/tls-gnu.c | 2 +- 20 files changed, 267 insertions(+), 215 deletions(-) (limited to 'src') diff --git a/src/src/acl.c b/src/src/acl.c index 5ab674776..17d6c68da 100644 --- a/src/src/acl.c +++ b/src/src/acl.c @@ -1092,7 +1092,7 @@ for (header_line * h = acl_added_headers; h; h = h->next) g = string_append_listele_n(g, '\n', h->text, i); } -return g ? g->s : NULL; +return string_from_gstring(g); } diff --git a/src/src/arc.c b/src/src/arc.c index 30a66320e..ef44672f8 100644 --- a/src/src/arc.c +++ b/src/src/arc.c @@ -261,8 +261,7 @@ while ((c = *s)) if (c != ' ' && c != '\t' && c != '\n' && c != '\r') g = string_catn(g, s, 1); if (!g) return US"no b= value"; - al->b.data = string_from_gstring(g); - al->b.len = g->ptr; + al->b.len = len_string_from_gstring(g, &al->b.data); gstring_release_unused(g); bend = s; break; @@ -278,8 +277,7 @@ while ((c = *s)) if (c != ' ' && c != '\t' && c != '\n' && c != '\r') g = string_catn(g, s, 1); if (!g) return US"no bh= value"; - al->bh.data = string_from_gstring(g); - al->bh.len = g->ptr; + al->bh.len = len_string_from_gstring(g, &al->bh.data); gstring_release_unused(g); break; default: @@ -1308,7 +1306,7 @@ header_line * h = (header_line *)(al+1); /* Construct the to-be-signed AMS pseudo-header: everything but the sig. */ -ams_off = g->ptr; +ams_off = gstring_length(g); g = string_fmt_append(g, "%s i=%d; a=rsa-sha256; c=relaxed; d=%s; s=%s", ARC_HDR_AMS, instance, identity, selector); /*XXX hardwired a= */ if (options & ARC_SIGN_OPT_TSTAMP) @@ -1352,7 +1350,7 @@ for(col = 3; rheaders; rheaders = rheaders->prev) /* Lose the last colon from the h= list */ -if (g->s[g->ptr - 1] == ':') g->ptr--; +gstring_trim_trailing(g, ':'); g = string_catn(g, US";\r\n\tb=;", 7); @@ -1370,7 +1368,7 @@ if (!arc_sig_from_pseudoheader(hdata, hashtype, privkey, &sig, US"AMS")) /* Lose the trailing semicolon from the psuedo-header, and append the signature (folded over lines) and termination to complete it. */ -g->ptr--; +gstring_trim(g, 1); g = arc_sign_append_sig(g, &sig); h->slen = g->ptr - ams_off; @@ -1548,7 +1546,7 @@ into the copies. static const uschar * arc_header_sign_feed(gstring * g) { -uschar * s = string_copyn(g->s, g->ptr); +uschar * s = string_copy_from_gstring(g); headers_rlist = arc_rlist_entry(headers_rlist, s, g->ptr); return arc_try_header(&arc_sign_ctx, headers_rlist->h, TRUE); } @@ -1772,10 +1770,9 @@ if (strncmpic(ARC_HDR_AMS, g->s, ARC_HDRLEN_AMS) != 0) return US"not AMS"; DEBUG(D_receive) debug_printf("ARC: spotted AMS header\n"); /* Parse the AMS header */ -h.next = NULL; -h.slen = g->size; -h.text = g->s; memset(&al, 0, sizeof(arc_line)); +h.next = NULL; +h.slen = len_string_from_gstring(g, &h.text); if ((errstr = arc_parse_line(&al, &h, ARC_HDRLEN_AMS, FALSE))) { DEBUG(D_acl) if (errstr) debug_printf("ARC: %s\n", errstr); @@ -1857,7 +1854,8 @@ for (as = arc_verify_ctx.arcset_chain, inst = 1; as; as = as->next, inst++) else g = string_catn(g, US":", 1); } -return g ? g->s : US""; +if (!g) return US""; +return string_from_gstring(g); } @@ -1870,7 +1868,7 @@ if (arc_state) { arc_line * highest_ams; int start = 0; /* Compiler quietening */ - DEBUG(D_acl) start = g->ptr; + DEBUG(D_acl) start = gstring_length(g); g = string_append(g, 2, US";\n\tarc=", arc_state); if (arc_received_instance > 0) @@ -1890,7 +1888,7 @@ if (arc_state) else if (arc_state_reason) g = string_append(g, 3, US" (", arc_state_reason, US")"); DEBUG(D_acl) debug_printf("ARC: authres '%.*s'\n", - g->ptr - start - 3, g->s + start + 3); + gstring_length(g) - start - 3, g->s + start + 3); } else DEBUG(D_acl) debug_printf("ARC: no authres\n"); diff --git a/src/src/deliver.c b/src/src/deliver.c index ca31df587..084a048c9 100644 --- a/src/src/deliver.c +++ b/src/src/deliver.c @@ -1045,7 +1045,7 @@ splitting is done; in those cases use the original field. */ else { uschar * cmp; - int off = g->ptr; /* start of the "full address" */ + int off = gstring_length(g); /* start of the "full address" */ if (addr->local_part) { @@ -1338,23 +1338,25 @@ if (LOGGING(deliver_time)) if (addr->message) g = string_append(g, 2, US": ", addr->message); -(void) string_from_gstring(g); + { + const uschar * s = string_from_gstring(g); -/* Log the deferment in the message log, but don't clutter it -up with retry-time defers after the first delivery attempt. */ + /* Log the deferment in the message log, but don't clutter it + up with retry-time defers after the first delivery attempt. */ -if (f.deliver_firsttime || addr->basic_errno > ERRNO_RETRY_BASE) - deliver_msglog("%s %s\n", now, g->s); + if (f.deliver_firsttime || addr->basic_errno > ERRNO_RETRY_BASE) + deliver_msglog("%s %s\n", now, s); -/* Write the main log and reset the store. -For errors of the type "retry time not reached" (also remotes skipped -on queue run), logging is controlled by L_retry_defer. Note that this kind -of error number is negative, and all the retry ones are less than any -others. */ + /* Write the main log and reset the store. + For errors of the type "retry time not reached" (also remotes skipped + on queue run), logging is controlled by L_retry_defer. Note that this kind + of error number is negative, and all the retry ones are less than any + others. */ -log_write(addr->basic_errno <= ERRNO_RETRY_BASE ? L_retry_defer : 0, logflags, - "== %s", g->s); + log_write(addr->basic_errno <= ERRNO_RETRY_BASE ? L_retry_defer : 0, logflags, + "== %s", s); + } store_reset(reset_point); return; @@ -1417,17 +1419,19 @@ if (addr->message) if (LOGGING(deliver_time)) g = string_append(g, 2, US" DT=", string_timediff(&addr->delivery_time)); -(void) string_from_gstring(g); - /* Do the logging. For the message log, "routing failed" for those cases, just to make it clearer. */ -if (driver_kind) - deliver_msglog("%s %s failed for %s\n", now, driver_kind, g->s); -else - deliver_msglog("%s %s\n", now, g->s); + { + const uschar * s = string_from_gstring(g); + + if (driver_kind) + deliver_msglog("%s %s failed for %s\n", now, driver_kind, s); + else + deliver_msglog("%s %s\n", now, s); -log_write(0, LOG_MAIN, "** %s", g->s); + log_write(0, LOG_MAIN, "** %s", s); + } store_reset(reset_point); return; diff --git a/src/src/dkim.c b/src/src/dkim.c index 0a8ab6fb3..4c19f752f 100644 --- a/src/src/dkim.c +++ b/src/src/dkim.c @@ -83,7 +83,7 @@ for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS); return string_from_gstring(g); } - g->ptr = 0; /* overwrite previous record */ + gstring_reset(g); /* overwrite previous record */ } bad: @@ -822,7 +822,7 @@ authres_dkim(gstring * g) { int start = 0; /* compiler quietening */ -DEBUG(D_acl) start = g->ptr; +DEBUG(D_acl) start = gstring_length(g); for (pdkim_signature * sig = dkim_signatures; sig; sig = sig->next) { @@ -884,7 +884,7 @@ for (pdkim_signature * sig = dkim_signatures; sig; sig = sig->next) } DEBUG(D_acl) - if (g->ptr == start) + if (gstring_length(g) == start) debug_printf("DKIM: no authres\n"); else debug_printf("DKIM: authres '%.*s'\n", g->ptr - start - 3, g->s + start + 3); diff --git a/src/src/exim.c b/src/src/exim.c index c5de167c6..dcc71ea45 100644 --- a/src/src/exim.c +++ b/src/src/exim.c @@ -203,15 +203,16 @@ Returns: nothing */ void -set_process_info(const char *format, ...) +set_process_info(const char * format, ...) { gstring gs = { .size = PROCESS_INFO_SIZE - 2, .ptr = 0, .s = process_info }; gstring * g; int len; +uschar * s; va_list ap; g = string_fmt_append(&gs, "%5d ", (int)getpid()); -len = g->ptr; +len = gstring_length(g); va_start(ap, format); if (!string_vformat(g, 0, format, ap)) { @@ -219,8 +220,7 @@ if (!string_vformat(g, 0, format, ap)) g = string_cat(&gs, US"**** string overflowed buffer ****"); } g = string_catn(g, US"\n", 1); -string_from_gstring(g); -process_info_len = g->ptr; +process_info_len = len_string_from_gstring(g, &s); DEBUG(D_process_info) debug_printf("set_process_info: %s", process_info); va_end(ap); } @@ -1501,10 +1501,10 @@ for (int i = 0;; i++) #endif /* g can only be NULL if ss==p */ - if (ss == p || g->s[g->ptr-1] != '\\') /* not continuation; done */ + if (ss == p || gstring_last_char(g) != '\\') /* not continuation; done */ break; - --g->ptr; /* drop the \ */ + gstring_trim(g, 1); /* drop the \ */ } if (had_input) return g ? string_from_gstring(g) : US""; diff --git a/src/src/expand.c b/src/src/expand.c index a7e6e4fb3..1daf10044 100644 --- a/src/src/expand.c +++ b/src/src/expand.c @@ -1667,12 +1667,13 @@ Returns: NULL if the header does not exist, else a pointer to a new */ static uschar * -find_header(uschar *name, int *newsize, unsigned flags, const uschar *charset) +find_header(uschar * name, int * newsize, unsigned flags, const uschar * charset) { BOOL found = !name; int len = name ? Ustrlen(name) : 0; BOOL comma = FALSE; gstring * g = NULL; +uschar * rawhdr; for (header_line * h = header_list; h; h = h->next) if (h->type != htype_old && h->text) /* NULL => Received: placeholder */ @@ -1735,8 +1736,9 @@ if (!g) return US""; /* That's all we do for raw header expansion. */ *newsize = g->size; +rawhdr = string_from_gstring(g); if (flags & FH_WANT_RAW) - return string_from_gstring(g); + return rawhdr; /* Otherwise do RFC 2047 decoding, translating the charset if requested. The rfc2047_decode2() function can return an error with decoded data if the @@ -1744,12 +1746,12 @@ charset translation fails. If decoding fails, it returns NULL. */ else { - uschar * error, * decoded = rfc2047_decode2(string_from_gstring(g), + uschar * error, * decoded = rfc2047_decode2(rawhdr, check_rfc2047_length, charset, '?', NULL, newsize, &error); if (error) DEBUG(D_any) debug_printf("*** error in RFC 2047 decoding: %s\n" - " input was: %s\n", error, g->s); - return decoded ? decoded : string_from_gstring(g); + " input was: %s\n", error, rawhdr); + return decoded ? decoded : rawhdr; } } @@ -1814,7 +1816,7 @@ for (int i = 0; i < recipients_count; i++) s = recipients_list[i].address; g = string_append2_listele_n(g, US", ", s, Ustrlen(s)); } -return g ? g->s : NULL; +return string_from_gstring(g); } @@ -4804,7 +4806,7 @@ while (*s) skipping, but "break" otherwise so we get debug output for the item expansion. */ { - int start = gstring_length(yield); + int expansion_start = gstring_length(yield); switch(item_type) { /* Call an ACL from an expansion. We feed data in via $acl_arg1 - $acl_arg9. @@ -4868,7 +4870,7 @@ while (*s) yield = string_append(yield, 3, US"Authentication-Results: ", sub_arg[0], US"; none"); - yield->ptr -= 6; + yield->ptr -= 6; /* ignore tha ": none" for now */ yield = authres_local(yield, sub_arg[0]); yield = authres_iprev(yield); @@ -5785,7 +5787,7 @@ while (*s) if (o2m >= 0) for (; oldptr < yield->ptr; oldptr++) { - uschar *m = Ustrrchr(sub[1], yield->s[oldptr]); + uschar * m = Ustrrchr(sub[1], yield->s[oldptr]); if (m) { int o = m - sub[1]; @@ -7107,7 +7109,7 @@ while (*s) it was for good reason */ if (quoted) yield = string_catn(yield, US"\"", 1); - yield = string_catn(yield, g->s, g->ptr); + yield = gstring_append(yield, g); if (quoted) yield = string_catn(yield, US"\"", 1); /* @$original_domain */ @@ -7126,10 +7128,11 @@ while (*s) } /* EITEM_* switch */ /*NOTREACHED*/ - DEBUG(D_expand) - if (yield && (start > 0 || *s)) /* only if not the sole expansion of the line */ + DEBUG(D_expand) /* only if not the sole expansion of the line */ + if (yield && (expansion_start > 0 || *s)) debug_expansion_interim(US"item-res", - yield->s + start, yield->ptr - start, !!(flags & ESI_SKIPPING)); + yield->s + expansion_start, yield->ptr - expansion_start, + !!(flags & ESI_SKIPPING)); continue; NOT_ITEM: ; @@ -7219,11 +7222,11 @@ NOT_ITEM: ; { case EOP_BASE32: { - uschar *t; + uschar * t; unsigned long int n = Ustrtoul(sub, &t, 10); gstring * g = NULL; - if (*t != 0) + if (*t) { expand_string_message = string_sprintf("argument for base32 " "operator is \"%s\", which is not a decimal number", sub); @@ -7832,16 +7835,19 @@ NOT_ITEM: ; case EOP_UTF8CLEAN: { - int seq_len = 0, index = 0; - int bytes_left = 0; + int seq_len = 0, index = 0, bytes_left = 0, complete; long codepoint = -1; - int complete; uschar seq_buff[4]; /* accumulate utf-8 here */ /* Manually track tainting, as we deal in individual chars below */ - if (!yield->s || !yield->ptr) + if (!yield) + yield = string_get_tainted(Ustrlen(sub), sub); + else if (!yield->s || !yield->ptr) + { yield->s = store_get(yield->size = Ustrlen(sub), sub); + gstring_reset(yield); + } else if (is_incompatible(yield->s, sub)) gstring_rebuffer(yield, sub); @@ -7967,7 +7973,7 @@ NOT_ITEM: ; goto EXPAND_FAILED; } yield = string_cat(yield, s); - DEBUG(D_expand) debug_printf_indent("yield: '%s'\n", yield->s); + DEBUG(D_expand) debug_printf_indent("yield: '%s'\n", string_from_gstring(yield)); break; } @@ -8276,7 +8282,8 @@ NOT_ITEM: ; DEBUG(D_expand) { - const uschar * s = yield->s + expansion_start; + const uschar * res = string_from_gstring(yield); + const uschar * s = res + expansion_start; int i = gstring_length(yield) - expansion_start; BOOL tainted = is_tainted(s); @@ -8286,7 +8293,7 @@ NOT_ITEM: ; if (tainted) { debug_printf_indent("%s \\__", flags & ESI_SKIPPING ? "| " : " "); - debug_print_taint(yield->s); + debug_print_taint(res); } } else @@ -8299,7 +8306,7 @@ NOT_ITEM: ; debug_printf_indent("%s", flags & ESI_SKIPPING ? UTF8_VERT " " : " " UTF8_UP_RIGHT UTF8_HORIZ UTF8_HORIZ); - debug_print_taint(yield->s); + debug_print_taint(res); } } } @@ -8374,58 +8381,62 @@ if (flags & ESI_BRACE_ENDS && !*s) added to the string. If so, set up an empty string. Add a terminating zero. If left != NULL, return a pointer to the terminator. */ -if (!yield) - yield = string_get(1); -(void) string_from_gstring(yield); -if (left) *left = s; + { + uschar * res; -/* Any stacking store that was used above the final string is no longer needed. -In many cases the final string will be the first one that was got and so there -will be optimal store usage. */ + if (!yield) + yield = string_get(1); + res = string_from_gstring(yield); + if (left) *left = s; -if (resetok) gstring_release_unused(yield); -else if (resetok_p) *resetok_p = FALSE; + /* Any stacking store that was used above the final string is no longer needed. + In many cases the final string will be the first one that was got and so there + will be optimal store usage. */ -DEBUG(D_expand) - { - BOOL tainted = is_tainted(yield->s); - DEBUG(D_noutf8) + if (resetok) gstring_release_unused(yield); + else if (resetok_p) *resetok_p = FALSE; + + DEBUG(D_expand) { - debug_printf_indent("|--expanding: %.*s\n", (int)(s - string), string); - debug_printf_indent("%sresult: %s\n", - flags & ESI_SKIPPING ? "|-----" : "\\_____", yield->s); - if (tainted) + BOOL tainted = is_tainted(res); + DEBUG(D_noutf8) { - debug_printf_indent("%s \\__", flags & ESI_SKIPPING ? "| " : " "); - debug_print_taint(yield->s); + debug_printf_indent("|--expanding: %.*s\n", (int)(s - string), string); + debug_printf_indent("%sresult: %s\n", + flags & ESI_SKIPPING ? "|-----" : "\\_____", res); + if (tainted) + { + debug_printf_indent("%s \\__", flags & ESI_SKIPPING ? "| " : " "); + debug_print_taint(res); + } + if (flags & ESI_SKIPPING) + debug_printf_indent("\\___skipping: result is not used\n"); } - if (flags & ESI_SKIPPING) - debug_printf_indent("\\___skipping: result is not used\n"); - } - else - { - debug_printf_indent(UTF8_VERT_RIGHT UTF8_HORIZ UTF8_HORIZ - "expanding: %.*s\n", - (int)(s - string), string); - debug_printf_indent("%s" UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ - "result: %s\n", - flags & ESI_SKIPPING ? UTF8_VERT_RIGHT : UTF8_UP_RIGHT, - yield->s); - if (tainted) + else { - debug_printf_indent("%s", - flags & ESI_SKIPPING - ? UTF8_VERT " " : " " UTF8_UP_RIGHT UTF8_HORIZ UTF8_HORIZ); - debug_print_taint(yield->s); + debug_printf_indent(UTF8_VERT_RIGHT UTF8_HORIZ UTF8_HORIZ + "expanding: %.*s\n", + (int)(s - string), string); + debug_printf_indent("%s" UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ + "result: %s\n", + flags & ESI_SKIPPING ? UTF8_VERT_RIGHT : UTF8_UP_RIGHT, + res); + if (tainted) + { + debug_printf_indent("%s", + flags & ESI_SKIPPING + ? UTF8_VERT " " : " " UTF8_UP_RIGHT UTF8_HORIZ UTF8_HORIZ); + debug_print_taint(res); + } + if (flags & ESI_SKIPPING) + debug_printf_indent(UTF8_UP_RIGHT UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ + "skipping: result is not used\n"); } - if (flags & ESI_SKIPPING) - debug_printf_indent(UTF8_UP_RIGHT UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ - "skipping: result is not used\n"); } - } -if (textonly_p) *textonly_p = textonly; -expand_level--; -return yield->s; + if (textonly_p) *textonly_p = textonly; + expand_level--; + return res; + } /* This is the failure exit: easiest to program with a goto. We still need to update the pointer to the terminator, for cases of nested calls with "fail". diff --git a/src/src/functions.h b/src/src/functions.h index 1817144ea..961db2dc0 100644 --- a/src/src/functions.h +++ b/src/src/functions.h @@ -963,12 +963,58 @@ g->s[g->ptr] = '\0'; return g->s; } +static inline int +len_string_from_gstring(gstring * g, uschar ** sp) +{ +if (g) + { + *sp = g->s; + g->s[g->ptr] = '\0'; + return g->ptr; + } +else + { + *sp = NULL; + return 0; + } +} + +static inline uschar * +string_copy_from_gstring(gstring * g) +{ +return g ? string_copyn(g->s, g->ptr) : NULL; +} + static inline unsigned gstring_length(const gstring * g) { return g ? (unsigned)g->ptr : 0; } +static inline uschar +gstring_last_char(gstring * g) +{ +return g->s[g->ptr-1]; +} + +static inline void +gstring_trim(gstring * g, unsigned amount) +{ +g->ptr -= amount; +} + +static inline void +gstring_trim_trailing(gstring * g, uschar c) +{ +if (gstring_last_char(g) == c) gstring_trim(g, 1); +} + +static inline void +gstring_reset(gstring * g) +{ +g->ptr = 0; +} + #define gstring_release_unused(g) \ gstring_release_unused_trc(g, __FUNCTION__, __LINE__) @@ -1014,6 +1060,13 @@ memcpy(s, g->s, g->ptr); g->s = s; } +/* Append one gstring to another */ +static inline gstring * +gstring_append(gstring * dest, gstring * item) +{ +return string_catn(dest, item->s, item->ptr); +} + # ifndef COMPILE_UTILITY /******************************************************************************/ diff --git a/src/src/imap_utf7.c b/src/src/imap_utf7.c index 1c09db621..6c9b5c179 100644 --- a/src/src/imap_utf7.c +++ b/src/src/imap_utf7.c @@ -200,9 +200,7 @@ iconv_close(icd); #endif yield = string_catn(yield, outbuf, outptr - outbuf); - -if (yield->s[yield->ptr-1] == '.') - yield->ptr--; +gstring_trim_trailing(yield, '.'); return string_from_gstring(yield); } diff --git a/src/src/log.c b/src/src/log.c index d11b933f9..08ece6158 100644 --- a/src/src/log.c +++ b/src/src/log.c @@ -684,11 +684,11 @@ Returns: length actually written, persisting an errno from write() */ ssize_t -write_to_fd_buf(int fd, const uschar *buf, size_t length) +write_to_fd_buf(int fd, const uschar * buf, size_t length) { ssize_t wrote; size_t total_written = 0; -const uschar *p = buf; +const uschar * p = buf; size_t left = length; while (1) @@ -711,6 +711,12 @@ while (1) return total_written; } +static inline ssize_t +write_gstring_to_fd_buf(int fd, const gstring * g) +{ +return write_to_fd_buf(fd, g->s, g->ptr); +} + static void @@ -1113,7 +1119,7 @@ if ( flags & LOG_MAIN /* Failing to write to the log is disastrous */ - written_len = write_to_fd_buf(mainlogfd, g->s, g->ptr); + written_len = write_gstring_to_fd_buf(mainlogfd, g); if (written_len != g->ptr) { log_write_failed(US"main log", g->ptr, written_len); @@ -1172,8 +1178,8 @@ if (flags & LOG_REJECT) g = g2; else /* Buffer is full; truncate */ { - g->ptr -= 100; /* For message and separator */ - if (g->s[g->ptr-1] == '\n') g->ptr--; + gstring_trim(g, 100); /* For message and separator */ + gstring_trim_trailing(g, '\n'); g = string_cat(g, US"\n*** truncated ***\n"); break; } @@ -1228,7 +1234,7 @@ if (flags & LOG_REJECT) if (fstat(rejectlogfd, &statbuf) >= 0) rejectlog_inode = statbuf.st_ino; } - written_len = write_to_fd_buf(rejectlogfd, g->s, g->ptr); + written_len = write_gstring_to_fd_buf(rejectlogfd, g); if (written_len != g->ptr) { log_write_failed(US"reject log", g->ptr, written_len); @@ -1263,7 +1269,7 @@ if (flags & LOG_PANIC) if (panic_save_buffer) (void) write(paniclogfd, panic_save_buffer, Ustrlen(panic_save_buffer)); - written_len = write_to_fd_buf(paniclogfd, g->s, g->ptr); + written_len = write_gstring_to_fd_buf(paniclogfd, g); if (written_len != g->ptr) { int save_errno = errno; diff --git a/src/src/lookups/dnsdb.c b/src/src/lookups/dnsdb.c index 5482cd9d1..1563eda56 100644 --- a/src/src/lookups/dnsdb.c +++ b/src/src/lookups/dnsdb.c @@ -136,15 +136,12 @@ dnsdb_find(void * handle, const uschar * filename, const uschar * keystring, { int rc; int sep = 0; -int defer_mode = PASS; -int dnssec_mode = PASS; -int save_retrans = dns_retrans; -int save_retry = dns_retry; +int defer_mode = PASS, dnssec_mode = PASS; +int save_retrans = dns_retrans, save_retry = dns_retry; int type; int failrc = FAIL; -const uschar *outsep = CUS"\n"; -const uschar *outsep2 = NULL; -uschar *equals, *domain, *found; +const uschar * outsep = CUS"\n", * outsep2 = NULL; +uschar * equals, * domain, * found; dns_answer * dnsa = store_get_dns_answer(); dns_scan dnss; @@ -385,10 +382,7 @@ while ((domain = string_nextinlist(&keystring, &sep, NULL, 0))) if (type == T_A || type == T_AAAA || type == T_ADDRESSES) { for (dns_address * da = dns_address_from_rr(dnsa, rr); da; da = da->next) - { - if (yield->ptr) yield = string_catn(yield, outsep, 1); - yield = string_cat(yield, da->address); - } + yield = string_append_listele(yield, *outsep, da->address); continue; } @@ -399,21 +393,17 @@ while ((domain = string_nextinlist(&keystring, &sep, NULL, 0))) if (type == T_TXT || type == T_SPF) { - if (outsep2 == NULL) /* output only the first item of data */ + if (!outsep2) /* output only the first item of data */ yield = string_catn(yield, US (rr->data+1), (rr->data)[0]); else - { - /* output all items */ - int data_offset = 0; - while (data_offset < rr->size) + for (unsigned data_offset = 0; data_offset < rr->size; ) { - uschar chunk_len = (rr->data)[data_offset++]; - if (outsep2[0] != '\0' && data_offset != 1) + uschar chunk_len = (rr->data)[data_offset]; + if (*outsep2 && data_offset != 0) yield = string_catn(yield, outsep2, 1); - yield = string_catn(yield, US ((rr->data)+data_offset), chunk_len); + yield = string_catn(yield, US ((rr->data) + ++data_offset), chunk_len); data_offset += chunk_len; } - } } else if (type == T_TLSA) { diff --git a/src/src/lookups/ldap.c b/src/src/lookups/ldap.c index b2ad3bbbc..82d6954ff 100644 --- a/src/src/lookups/ldap.c +++ b/src/src/lookups/ldap.c @@ -326,17 +326,19 @@ if (!lcp) g = string_catn(NULL, ldap_url, init_ptr - ldap_url); g = string_fmt_append(g, "//%s:%d/", shost, port); } - string_from_gstring(g); /* Call ldap_initialize() and check the result */ + { + const uschar * s = string_from_gstring(g); - DEBUG(D_lookup) debug_printf_indent("ldap_initialize with URL %s\n", g->s); - if ((rc = ldap_initialize(&ld, CS g->s)) != LDAP_SUCCESS) - { - *errmsg = string_sprintf("ldap_initialize: (error %d) URL \"%s\"\n", - rc, g->s); - goto RETURN_ERROR; - } + DEBUG(D_lookup) debug_printf_indent("ldap_initialize with URL %s\n", s); + if ((rc = ldap_initialize(&ld, CS s)) != LDAP_SUCCESS) + { + *errmsg = string_sprintf("ldap_initialize: (error %d) URL \"%s\"\n", + rc, s); + goto RETURN_ERROR; + } + } store_reset(reset_point); /* Might as well save memory when we can */ diff --git a/src/src/mime.c b/src/src/mime.c index 7c3a33d62..d4c26540a 100644 --- a/src/src/mime.c +++ b/src/src/mime.c @@ -755,7 +755,7 @@ while(1) int result = 0; /* must find first free sequential filename */ - for (gstring * g = string_get(64); result != -1; g->ptr = 0) + for (gstring * g = string_get(64); result != -1; gstring_reset(g)) { struct stat mystat; g = string_fmt_append(g, diff --git a/src/src/parse.c b/src/src/parse.c index 53d660869..ead8751ae 100644 --- a/src/src/parse.c +++ b/src/src/parse.c @@ -875,26 +875,26 @@ Returns: pointer to the original string, if no quoting needed, or */ const uschar * -parse_quote_2047(const uschar *string, int len, const uschar *charset, +parse_quote_2047(const uschar * string, int len, const uschar * charset, BOOL fold) { const uschar * s = string; -int hlen, l; +int hlen, line_off; BOOL coded = FALSE; BOOL first_byte = FALSE; gstring * g = - string_fmt_append(NULL, "=?%s?Q?", charset ? charset : US"iso-8859-1"); + string_fmt_append(NULL, "=?%s?Q?%n", charset ? charset : US"iso-8859-1", &hlen); -hlen = l = g->ptr; +line_off = hlen; for (s = string; len > 0; s++, len--) { int ch = *s; - if (g->ptr - l > 67 && !first_byte) + if (g->ptr - line_off > 67 && !first_byte) { g = fold ? string_catn(g, US"?=\n ", 4) : string_catn(g, US"?= ", 3); - l = g->ptr; + line_off = g->ptr; g = string_catn(g, g->s, hlen); } diff --git a/src/src/pdkim/pdkim.c b/src/src/pdkim/pdkim.c index eb26b3864..c8f180a58 100644 --- a/src/src/pdkim/pdkim.c +++ b/src/src/pdkim/pdkim.c @@ -957,9 +957,8 @@ return; static int pdkim_header_complete(pdkim_ctx * ctx) { -if ( (ctx->cur_header->ptr > 1) && - (ctx->cur_header->s[ctx->cur_header->ptr-1] == '\r') ) - --ctx->cur_header->ptr; +if (ctx->cur_header->ptr > 1) + gstring_trim_trailing(ctx->cur_header, '\r'); (void) string_from_gstring(ctx->cur_header); #ifdef EXPERIMENTAL_ARC diff --git a/src/src/readconf.c b/src/src/readconf.c index 48b648bb2..6dba11ca1 100644 --- a/src/src/readconf.c +++ b/src/src/readconf.c @@ -3219,7 +3219,7 @@ if (config_file) g = string_cat(NULL, buf); /* If the dir does not end with a "/", append one */ - if (g->s[g->ptr-1] != '/') + if (gstring_last_char(g) != '/') g = string_catn(g, US"/", 1); /* If the config file contains a "/", extract the directory part */ diff --git a/src/src/receive.c b/src/src/receive.c index 9bf834aaf..77665d89f 100644 --- a/src/src/receive.c +++ b/src/src/receive.c @@ -4214,7 +4214,8 @@ if (message_logs && !blackholed_by) } else { - uschar *now = tod_stamp(tod_log); + uschar * now = tod_stamp(tod_log); + /* Drop the initial "<= " */ fprintf(message_log, "%s Received from %s\n", now, g->s+3); if (f.deliver_freeze) fprintf(message_log, "%s frozen by %s\n", now, frozen_by); @@ -4266,7 +4267,7 @@ if ( smtp_input && sender_host_address && !f.sender_host_notsocket /* Re-use the log line workspace */ - g->ptr = 0; + gstring_reset(g); g = string_cat(g, US"SMTP connection lost after final dot"); g = add_host_info_for_log(g); log_write(0, LOG_MAIN, "%s", string_from_gstring(g)); diff --git a/src/src/rfc2047.c b/src/src/rfc2047.c index c40518a5d..d5e33b9b1 100644 --- a/src/src/rfc2047.c +++ b/src/src/rfc2047.c @@ -192,9 +192,9 @@ rfc2047_decode2(uschar *string, BOOL lencheck, const uschar *target, { int size = Ustrlen(string); size_t dlen; -uschar *dptr; -gstring *yield; -uschar *mimeword, *q1, *q2, *endword; +uschar * dptr; +gstring * yield; +uschar * mimeword, * q1, * q2, * endword; *error = NULL; mimeword = decode_mimeword(string, lencheck, &q1, &q2, &endword, &dlen, &dptr); @@ -210,17 +210,14 @@ building the result as we go. The result may be longer than the input if it is translated into a multibyte code such as UTF-8. That's why we use the dynamic string building code. */ -yield = store_get(sizeof(gstring) + ++size, string); -yield->size = size; -yield->ptr = 0; -yield->s = US(yield + 1); +yield = string_get_tainted(++size, string); while (mimeword) { - #if HAVE_ICONV +#if HAVE_ICONV iconv_t icd = (iconv_t)(-1); - #endif +#endif if (mimeword != string) yield = string_catn(yield, string, mimeword - string); @@ -233,7 +230,7 @@ while (mimeword) of long strings - the RFC puts limits on the length, but it's best to be robust. */ - #if HAVE_ICONV +#if HAVE_ICONV *q1 = 0; if (target && strcmpic(target, mimeword+2) != 0) if ((icd = iconv_open(CS target, CS(mimeword+2))) == (iconv_t)-1) @@ -241,14 +238,14 @@ while (mimeword) target, mimeword+2, strerror(errno), (errno == EINVAL)? " (maybe unsupported conversion)" : ""); *q1 = '?'; - #endif +#endif while (dlen > 0) { uschar *tptr = NULL; /* Stops compiler warning */ int tlen = -1; - #if HAVE_ICONV +#if HAVE_ICONV uschar tbuffer[256]; uschar *outptr = tbuffer; size_t outleft = sizeof(tbuffer); @@ -281,7 +278,7 @@ while (mimeword) } } - #endif +#endif /* No charset translation is happening or there was a translation error; just set up the original as the string to be added, and mark it all used. @@ -305,9 +302,9 @@ while (mimeword) yield = string_catn(yield, tptr, tlen); } - #if HAVE_ICONV +#if HAVE_ICONV if (icd != (iconv_t)(-1)) iconv_close(icd); - #endif +#endif /* Update string past the MIME word; skip any white space if the next thing is another MIME word. */ diff --git a/src/src/sieve.c b/src/src/sieve.c index 0b347e48d..4793d5756 100644 --- a/src/src/sieve.c +++ b/src/src/sieve.c @@ -439,8 +439,7 @@ if (*uri && *uri!='?') { gstring * g = string_catn(NULL, start, uri-start); - to.character = string_from_gstring(g); - to.length = g->ptr; + to.length = len_string_from_gstring(g, &to.character); if (uri_decode(&to)==-1) { filter->errmsg=US"Invalid URI encoding"; @@ -472,8 +471,7 @@ if (*uri=='?') { gstring * g = string_catn(NULL, start, uri-start); - hname.character = string_from_gstring(g); - hname.length = g->ptr; + hname.length = len_string_from_gstring(g, &hname.character); if (uri_decode(&hname)==-1) { filter->errmsg=US"Invalid URI encoding"; @@ -494,8 +492,7 @@ if (*uri=='?') { gstring * g = string_catn(NULL, start, uri-start); - hname.character = string_from_gstring(g); - hname.length = g->ptr; + hname.length = len_string_from_gstring(g, &hname.character); if (uri_decode(&hvalue)==-1) { filter->errmsg=US"Invalid URI encoding"; @@ -541,8 +538,7 @@ if (*uri=='?') g = string_catn(g, hvalue.character, hvalue.length); g = string_catn(g, CUS "\n", 1); - header->character = string_from_gstring(g); - header->length = g->ptr; + hname.length = len_string_from_gstring(g, &hname.character); } } if (*uri=='&') ++uri; @@ -1482,10 +1478,7 @@ if (*filter->pc=='"') /* quoted string */ ++filter->pc; if (g) - { - data->character = string_from_gstring(g); - data->length = g->ptr; - } + data->length = len_string_from_gstring(g, &data->character); else data->character = US"\0"; /* that way, there will be at least one character allocated */ @@ -1569,10 +1562,7 @@ else if (Ustrncmp(filter->pc,CUS "text:",5)==0) /* multiline string */ #endif { if (g) - { - data->character = string_from_gstring(g); - data->length = g->ptr; - } + data->length = len_string_from_gstring(g, &data->character); else data->character = US"\0"; /* that way, there will be at least one character allocated */ @@ -3303,7 +3293,7 @@ while (*filter->pc) if (subject.length==-1) { - uschar *subject_def; + uschar * subject_def; subject_def = expand_string(US"${if def:header_subject {true}{false}}"); if (subject_def && Ustrcmp(subject_def,"true")==0) @@ -3312,13 +3302,12 @@ while (*filter->pc) expand_header(&subject,&str_subject); g = string_catn(g, subject.character, subject.length); - subject.character = string_from_gstring(g); - subject.length = g->ptr; + subject.length = len_string_from_gstring(g, &subject.character); } else { - subject.character=US"Automated reply"; - subject.length=Ustrlen(subject.character); + subject.character = US"Automated reply"; + subject.length = Ustrlen(subject.character); } } diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c index 04b20d27c..a13af867a 100644 --- a/src/src/smtp_in.c +++ b/src/src/smtp_in.c @@ -4508,7 +4508,7 @@ while (done <= 0) if (fl.esmtp) { - g->s[3] = '-'; + g->s[3] = '-'; /* overwrite the space after the SMTP response code */ /* I'm not entirely happy with this, as an MTA is supposed to check that it has enough room to accept a message of maximum size before @@ -4639,9 +4639,9 @@ while (done <= 0) first = FALSE; fl.auth_advertised = TRUE; } - saveptr = g->ptr; + saveptr = gstring_length(g); g = string_catn(g, US" ", 1); - g = string_cat (g, au->public_name); + g = string_cat(g, au->public_name); while (++saveptr < g->ptr) g->s[saveptr] = toupper(g->s[saveptr]); au->advertised = TRUE; } @@ -4704,25 +4704,29 @@ while (done <= 0) /* Terminate the string (for debug), write it, and note that HELO/EHLO has been seen. */ + { + uschar * ehlo_resp; + int len = len_string_from_gstring(g, &ehlo_resp); #ifndef DISABLE_TLS - if (tls_in.active.sock >= 0) - (void)tls_write(NULL, g->s, g->ptr, + if (tls_in.active.sock >= 0) + (void) tls_write(NULL, ehlo_resp, len, # ifndef DISABLE_PIPE_CONNECT - fl.pipe_connect_acceptable && pipeline_connect_sends()); + fl.pipe_connect_acceptable && pipeline_connect_sends()); # else - FALSE); + FALSE); # endif - else + else #endif - (void) fwrite(g->s, 1, g->ptr, smtp_out); - - DEBUG(D_receive) for (const uschar * t, * s = string_from_gstring(g); - s && (t = Ustrchr(s, '\r')); - s = t + 2) /* \r\n */ - debug_printf("%s %.*s\n", - s == g->s ? "SMTP>>" : " ", - (int)(t - s), s); - fl.helo_seen = TRUE; + (void) fwrite(ehlo_resp, 1, len, smtp_out); + + DEBUG(D_receive) for (const uschar * t, * s = ehlo_resp; + s && (t = Ustrchr(s, '\r')); + s = t + 2) /* \r\n */ + debug_printf("%s %.*s\n", + s == g->s ? "SMTP>>" : " ", + (int)(t - s), s); + fl.helo_seen = TRUE; + } /* Reset the protocol and the state, abandoning any previous message. */ received_protocol = diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c index b47fabf1d..f3f70d2e0 100644 --- a/src/src/tls-gnu.c +++ b/src/src/tls-gnu.c @@ -2302,7 +2302,7 @@ old_pool = store_pool; for (s++; (c = *s) && c != ')'; s++) g = string_catn(g, s, 1); - tlsp->ver = string_copyn(g->s, g->ptr); + tlsp->ver = string_copy_from_gstring(g); for (uschar * p = US tlsp->ver; *p; p++) if (*p == '-') { *p = '\0'; break; } /* TLS1.0-PKIX -> TLS1.0 */ -- cgit v1.2.1