summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Harris <jgh146exb@wizmail.org>2023-02-05 16:04:14 +0000
committerJeremy Harris <jgh146exb@wizmail.org>2023-02-05 21:30:14 +0000
commit63deec8a3ba77fcabf405d9c30fdd65a8b909526 (patch)
treeea10e26087b3d512e04241cda01b4e87a313e070
parent6d179d5ef22fcdfc4802db3fbb37f88190186367 (diff)
downloadexim4-63deec8a3ba77fcabf405d9c30fdd65a8b909526.tar.gz
More abstraction of the gstring API
-rw-r--r--src/src/acl.c2
-rw-r--r--src/src/arc.c26
-rw-r--r--src/src/deliver.c44
-rw-r--r--src/src/dkim.c6
-rw-r--r--src/src/exim.c12
-rw-r--r--src/src/expand.c143
-rw-r--r--src/src/functions.h53
-rw-r--r--src/src/imap_utf7.c4
-rw-r--r--src/src/log.c20
-rw-r--r--src/src/lookups/dnsdb.c30
-rw-r--r--src/src/lookups/ldap.c18
-rw-r--r--src/src/mime.c2
-rw-r--r--src/src/parse.c12
-rw-r--r--src/src/pdkim/pdkim.c5
-rw-r--r--src/src/readconf.c2
-rw-r--r--src/src/receive.c5
-rw-r--r--src/src/rfc2047.c27
-rw-r--r--src/src/sieve.c31
-rw-r--r--src/src/smtp_in.c38
-rw-r--r--src/src/tls-gnu.c2
20 files changed, 267 insertions, 215 deletions
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 */