From: Jeremy Harris Date: Thu, 6 Jul 2023 23:40:43 +0000 (+0100) Subject: Support gring as a first-class conversion specifier in internal string-formatting X-Git-Tag: exim-4.97-RC0~58 X-Git-Url: https://git.exim.org/exim.git/commitdiff_plain/00392be0e7cfb5c6c6ce173ff31d81ab2a2e8779?hp=2b3ac4f13c815ad1b0d59165f2f441f8e4cc6b99 Support gring as a first-class conversion specifier in internal string-formatting --- diff --git a/src/src/auths/heimdal_gssapi.c b/src/src/auths/heimdal_gssapi.c index 1336d0fab..7a74d5be5 100644 --- a/src/src/auths/heimdal_gssapi.c +++ b/src/src/auths/heimdal_gssapi.c @@ -565,9 +565,8 @@ do { if (!auth_defer_msg) auth_defer_msg = string_copy(US status_string.value); - HDEBUG(D_auth) debug_printf("heimdal %s: %.*s\n", - string_from_gstring(g), (int)status_string.length, - CS status_string.value); + HDEBUG(D_auth) debug_printf("heimdal %Y: %.*s\n", + g, (int)status_string.length, CS status_string.value); gss_release_buffer(&min_stat, &status_string); } while (msgcontext != 0); diff --git a/src/src/daemon.c b/src/src/daemon.c index ea7db0f25..f6867b882 100644 --- a/src/src/daemon.c +++ b/src/src/daemon.c @@ -254,8 +254,6 @@ if (LOGGING(incoming_interface)) whofrom = string_fmt_append(whofrom, " I=[%s]:%d", interface_address, interface_port); -(void) string_from_gstring(whofrom); /* Terminate the newly-built string */ - /* Check maximum number of connections. We do not check for reserved connections or unacceptable hosts here. That is done in the subprocess because it might take some time. */ @@ -267,8 +265,8 @@ if (smtp_accept_max > 0 && smtp_accept_count >= smtp_accept_max) smtp_printf("421 Too many concurrent SMTP connections; " "please try again later.\r\n", FALSE); log_write(L_connection_reject, - LOG_MAIN, "Connection from %s refused: too many connections", - whofrom->s); + LOG_MAIN, "Connection from %Y refused: too many connections", + whofrom); goto ERROR_RETURN; } @@ -286,8 +284,8 @@ if (smtp_load_reserve >= 0) (double)load_average/1000.0); smtp_printf("421 Too much load; please try again later.\r\n", FALSE); log_write(L_connection_reject, - LOG_MAIN, "Connection from %s refused: load average = %.2f", - whofrom->s, (double)load_average/1000.0); + LOG_MAIN, "Connection from %Y refused: load average = %.2f", + whofrom, (double)load_average/1000.0); goto ERROR_RETURN; } } @@ -307,7 +305,7 @@ if (smtp_accept_max_per_host) { if (!f.expand_string_forcedfail) log_write(0, LOG_MAIN|LOG_PANIC, "expansion of smtp_accept_max_per_host " - "failed for %s: %s", whofrom->s, expand_string_message); + "failed for %Y: %s", whofrom, expand_string_message); } /* For speed, interpret a decimal number inline here */ else @@ -317,7 +315,7 @@ if (smtp_accept_max_per_host) max_for_this_host = max_for_this_host * 10 + *s++ - '0'; if (*s) log_write(0, LOG_MAIN|LOG_PANIC, "expansion of smtp_accept_max_per_host " - "for %s contains non-digit: %s", whofrom->s, expanded); + "for %Y contains non-digit: %s", whofrom, expanded); } } @@ -355,8 +353,8 @@ if (max_for_this_host > 0 && smtp_accept_count >= max_for_this_host) smtp_printf("421 Too many concurrent SMTP connections " "from this IP address; please try again later.\r\n", FALSE); log_write(L_connection_reject, - LOG_MAIN, "Connection from %s refused: too many connections " - "from that IP address", whofrom->s); + LOG_MAIN, "Connection from %Y refused: too many connections " + "from that IP address", whofrom); search_tidyup(); goto ERROR_RETURN; } @@ -382,8 +380,8 @@ if (LOGGING(smtp_connection)) if (list && verify_check_host(&list) == OK) save_log_selector &= ~L_smtp_connection; else - log_write(L_smtp_connection, LOG_MAIN, "SMTP connection from %s " - "(TCP/IP connection count = %d)", whofrom->s, smtp_accept_count + 1); + log_write(L_smtp_connection, LOG_MAIN, "SMTP connection from %Y " + "(TCP/IP connection count = %d)", whofrom, smtp_accept_count + 1); } /* Now we can fork the accepting process; do a lookup tidy, just in case any diff --git a/src/src/dcc.c b/src/src/dcc.c index 98f978fa9..e7a932426 100644 --- a/src/src/dcc.c +++ b/src/src/dcc.c @@ -237,11 +237,11 @@ for (int i = 0; i < recipients_count; i++) } /* send a blank line between options and message */ dcc_headers = string_catn(dcc_headers, US"\n", 1); + /* Now we send the input buffer */ -(void) string_from_gstring(dcc_headers); DEBUG(D_acl) - debug_printf("DCC: ***********************************\nDCC: Sending options:\n%s" - "DCC: ***********************************\n", dcc_headers->s); + debug_printf("DCC: ***********************************\nDCC: Sending options:\n%Y" + "DCC: ***********************************\n", dcc_headers); if (flushbuffer(sockfd, dcc_headers) != 0) { (void)fclose(data_file); @@ -259,10 +259,9 @@ while((mail_headers=mail_headers->next)) /* a blank line separates header from body */ sendbuf = string_catn(sendbuf, US"\r\n", 2); -(void) string_from_gstring(sendbuf); gstring_release_unused(sendbuf); DEBUG(D_acl) - debug_printf("%sDCC: ***********************************\n", sendbuf->s); + debug_printf("%YDCC: ***********************************\n", sendbuf); if (flushbuffer(sockfd, sendbuf) != 0) { (void)fclose(data_file); @@ -449,23 +448,23 @@ dcc_header_str = string_catn(dcc_header_str, US"\n", 1); /* Now let's sum up what we've got. */ DEBUG(D_acl) debug_printf("\nDCC: --------------------------\nDCC: Overall result = %d\n" - "DCC: X-DCC header: %sReturn message: %s\nDCC: dcc_result: %s\n", - retval, dcc_header_str->s, dcc_return_text, dcc_result); + "DCC: X-DCC header: %YReturn message: %s\nDCC: dcc_result: %s\n", + retval, dcc_header_str, dcc_return_text, dcc_result); /* We only add the X-DCC header if it starts with X-DCC */ if(!(Ustrncmp(dcc_header_str->s, "X-DCC", 5))) { - dcc_header = dcc_header_str->s; + dcc_header = string_from_gstring(dcc_header_str); if(dcc_direct_add_header) { - header_add(' ' , "%s", dcc_header_str->s); + header_add(' ' , "%s", dcc_header); /* since the MIME ACL already writes the .eml file to disk without DCC Header we've to erase it */ unspool_mbox(); } } else DEBUG(D_acl) - debug_printf("DCC: Wrong format of the X-DCC header: %.*s\n", dcc_header_str->ptr, dcc_header_str->s); + debug_printf("DCC: Wrong format of the X-DCC header: %Y\n", dcc_header_str); /* check if we should add additional headers passed in acl_m_dcc_add_header */ if (dcc_direct_add_header) @@ -477,7 +476,7 @@ if (dcc_direct_add_header) dcc_xtra_hdrs = string_catn(dcc_xtra_hdrs, US"\n", 1); header_add(' ', "%s", string_from_gstring(dcc_xtra_hdrs)); DEBUG(D_acl) - debug_printf("DCC: adding additional headers in $acl_m_dcc_add_header: %.*s", dcc_xtra_hdrs->ptr, dcc_xtra_hdrs->s); + debug_printf("DCC: adding additional headers in $acl_m_dcc_add_header: %Y", dcc_xtra_hdrs); } } diff --git a/src/src/debug.c b/src/src/debug.c index 44ad763e1..dac738470 100644 --- a/src/src/debug.c +++ b/src/src/debug.c @@ -439,7 +439,7 @@ if (fstat(fd, &s) == 0 && (s.st_mode & S_IFMT) == S_IFSOCK) : string_fmt_append(g, " proto %d", val); } #endif - debug_printf_indent(" socket: %s\n", string_from_gstring(g)); + debug_printf_indent(" socket: %Y\n", g); } else debug_printf_indent(" fd st_mode 0%o\n", s.st_mode); diff --git a/src/src/deliver.c b/src/src/deliver.c index 8f0f350d7..bea38c5d1 100644 --- a/src/src/deliver.c +++ b/src/src/deliver.c @@ -723,7 +723,7 @@ child_done(address_item * addr, const uschar * now) { while (addr->parent) { - address_item *aa; + address_item * aa; addr = addr->parent; if (--addr->child_count > 0) return; /* Incomplete parent */ @@ -1278,7 +1278,7 @@ if (LOGGING(deliver_time)) /* string_cat() always leaves room for the terminator. Release the store we used to build the line after writing it. */ -log_write(0, flags, "%s", string_from_gstring(g)); +log_write(0, flags, "%Y", g); #ifndef DISABLE_EVENT if (!msg) msg_event_raise(US"msg:delivery", addr); @@ -1337,25 +1337,21 @@ if (LOGGING(deliver_time)) if (addr->message) g = string_append(g, 2, US": ", addr->message); - { - 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->ptr, 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", s); - } +log_write(addr->basic_errno <= ERRNO_RETRY_BASE ? L_retry_defer : 0, logflags, + "== %Y", g); store_reset(reset_point); return; @@ -1421,16 +1417,12 @@ if (LOGGING(deliver_time)) /* Do the logging. For the message log, "routing failed" for those cases, just to make it clearer. */ - { - 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); +if (driver_kind) + deliver_msglog("%s %s failed for %.*s\n", now, driver_kind, g->ptr, g->s); +else + deliver_msglog("%s %.*s\n", now, g->ptr, g->s); - log_write(0, LOG_MAIN, "** %s", s); - } +log_write(0, LOG_MAIN, "** %Y", g); store_reset(reset_point); return; @@ -5989,7 +5981,7 @@ wording. */ if (rc != 0) { - uschar *s = US""; + uschar * s = US""; if (now - received_time.tv_sec < retry_maximum_timeout && !addr_defer) { addr_defer = (address_item *)(+1); diff --git a/src/src/dkim.c b/src/src/dkim.c index 4c19f752f..068b802e0 100644 --- a/src/src/dkim.c +++ b/src/src/dkim.c @@ -289,7 +289,7 @@ else break; } -log_write(0, LOG_MAIN, "%s", string_from_gstring(logmsg)); +log_write(0, LOG_MAIN, "%Y", logmsg); return; } diff --git a/src/src/dmarc.c b/src/src/dmarc.c index 555e3a72b..409d8a47d 100644 --- a/src/src/dmarc.c +++ b/src/src/dmarc.c @@ -306,7 +306,7 @@ DEBUG(D_receive) if (host_checking || f.running_in_test_harness) { DEBUG(D_receive) - debug_printf("DMARC history data for debugging:\n%s", string_from_gstring(g)); + debug_printf("DMARC history data for debugging:\n%Y", g); } else { diff --git a/src/src/expand.c b/src/src/expand.c index de00c7254..55c53957e 100644 --- a/src/src/expand.c +++ b/src/src/expand.c @@ -3957,10 +3957,9 @@ if (Ustrlen(key) > 64) hash_source = string_catn(NULL, key_num, 1); hash_source = string_catn(hash_source, daystamp, 3); hash_source = string_cat(hash_source, address); -(void) string_from_gstring(hash_source); DEBUG(D_expand) - debug_printf_indent("prvs: hash source is '%s'\n", hash_source->s); + debug_printf_indent("prvs: hash source is '%Y'\n", hash_source); memset(innerkey, 0x36, 64); memset(outerkey, 0x5c, 64); @@ -7993,7 +7992,7 @@ NOT_ITEM: ; goto EXPAND_FAILED; } yield = string_cat(yield, s); - DEBUG(D_expand) debug_printf_indent("yield: '%s'\n", string_from_gstring(yield)); + DEBUG(D_expand) debug_printf_indent("yield: '%Y'\n", yield); break; } diff --git a/src/src/header.c b/src/src/header.c index 59a9a13b3..97fa44b4e 100644 --- a/src/src/header.c +++ b/src/src/header.c @@ -110,7 +110,7 @@ gs.ptr = 0; if (!string_vformat(&gs, SVFMT_REBUFFER, format, ap)) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "string too long in header_add: " - "%.100s ...", string_from_gstring(&gs)); + "%.100Y ...", &gs); if (gs.s != buf) store_release_above(buf); gstring_release_unused(&gs); diff --git a/src/src/log.c b/src/src/log.c index 54d2b8027..fac577d5a 100644 --- a/src/src/log.c +++ b/src/src/log.c @@ -958,8 +958,7 @@ DEBUG(D_any|D_v) } va_end(ap); - g = string_catn(g, US"\n", 1); - debug_printf("%s", string_from_gstring(g)); + debug_printf("%Y\n", g); gs.size = LOG_BUFFER_SIZE-2; /* Having used the buffer for debug output, */ gs.ptr = 0; /* reset it for the real use. */ diff --git a/src/src/lookups/pgsql.c b/src/src/lookups/pgsql.c index 1583378d5..5d52f28b1 100644 --- a/src/src/lookups/pgsql.c +++ b/src/src/lookups/pgsql.c @@ -293,7 +293,7 @@ switch(PQresultStatus(pg_result)) result = string_cat(result, US PQcmdTuples(pg_result)); *do_cache = 0; DEBUG(D_lookup) debug_printf_indent("PGSQL: command does not return any data " - "but was successful. Rows affected: %s\n", string_from_gstring(result)); + "but was successful. Rows affected: %Y\n", result); break; case PGRES_TUPLES_OK: diff --git a/src/src/mime.c b/src/src/mime.c index d4c26540a..7d30b5462 100644 --- a/src/src/mime.c +++ b/src/src/mime.c @@ -489,7 +489,7 @@ while ((c = *fname)) val = string_catn(val, fname++, 1); val = string_catn(val, US"?=", 2); -*len = val->ptr; +*len = gstring_length(val); return string_from_gstring(val); } diff --git a/src/src/receive.c b/src/src/receive.c index acb3c40fc..0891a4a8c 100644 --- a/src/src/receive.c +++ b/src/src/receive.c @@ -3915,8 +3915,8 @@ else sender_address[0] == 0 ? US"<>" : sender_address); g = add_host_info_for_log(g); - log_write(0, LOG_MAIN|LOG_REJECT, "%s %srejected by local_scan(): %.256s", - string_from_gstring(g), istemp, string_printing(errmsg)); + log_write(0, LOG_MAIN|LOG_REJECT, "%Y %srejected by local_scan(): %.256s", + g, istemp, string_printing(errmsg)); if (smtp_input) if (!smtp_batched_input) @@ -4271,7 +4271,7 @@ if ( smtp_input && sender_host_address && !f.sender_host_notsocket 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)); + log_write(0, LOG_MAIN, "%Y", g); /* Delete the files for this aborted message. */ @@ -4337,7 +4337,7 @@ if(!smtp_reply) log_write(0, LOG_MAIN | (LOGGING(received_recipients) ? LOG_RECIPIENTS : 0) | (LOGGING(received_sender) ? LOG_SENDER : 0), - "%s", g->s); + "%Y", g); /* Log any control actions taken by an ACL or local_scan(). */ diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c index cd759df7b..e6f9808dd 100644 --- a/src/src/smtp_in.c +++ b/src/src/smtp_in.c @@ -2680,13 +2680,13 @@ if (!check_sync()) /* Now output the banner */ /*XXX the ehlo-resp code does its own tls/nontls bit. Maybe subroutine that? */ -smtp_printf("%s", +smtp_printf("%Y", #ifndef DISABLE_PIPE_CONNECT fl.pipe_connect_acceptable && pipeline_connect_sends(), #else FALSE, #endif - string_from_gstring(ss)); + ss); /* Attempt to see if we sent the banner before the last ACK of the 3-way handshake arrived. If so we must have managed a TFO. */ @@ -2735,9 +2735,9 @@ if (++synprot_error_count > smtp_max_synprot_errors) { yield = 1; log_write(0, LOG_MAIN|LOG_REJECT, "SMTP call from %s dropped: too many " - "syntax or protocol errors (last command was \"%s\", %s)", + "syntax or protocol errors (last command was \"%s\", %Y)", host_and_ident(FALSE), string_printing(smtp_cmd_buffer), - string_from_gstring(s_connhad_log(NULL)) + s_connhad_log(NULL) ); } @@ -3195,7 +3195,7 @@ if (code && defaultrespond) va_start(ap, defaultrespond); g = string_vformat(NULL, SVFMT_EXTEND|SVFMT_REBUFFER, CS defaultrespond, ap); va_end(ap); - smtp_printf("%s %s\r\n", FALSE, code, string_from_gstring(g)); + smtp_printf("%s %Y\r\n", FALSE, code, g); } mac_smtp_fflush(); } @@ -3872,9 +3872,9 @@ while (done <= 0) if (++synprot_error_count > smtp_max_synprot_errors) { log_write(0, LOG_MAIN|LOG_REJECT, "SMTP call from %s dropped: too many " - "syntax or protocol errors (last command was \"%s\", %s)", + "syntax or protocol errors (last command was \"%s\", %Y)", host_and_ident(FALSE), string_printing(smtp_cmd_buffer), - string_from_gstring(s_connhad_log(NULL)) + s_connhad_log(NULL) ); done = 1; } diff --git a/src/src/smtp_out.c b/src/src/smtp_out.c index 02f1fa438..7f477ed76 100644 --- a/src/src/smtp_out.c +++ b/src/src/smtp_out.c @@ -680,7 +680,6 @@ if (format) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "overlong write_command in outgoing " "SMTP"); va_end(ap); - string_from_gstring(&gs); if (gs.ptr > outblock->buffersize) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "overlong write_command in outgoing " diff --git a/src/src/string.c b/src/src/string.c index 0ea98d47d..854cf0d34 100644 --- a/src/src/string.c +++ b/src/src/string.c @@ -1327,6 +1327,11 @@ If the "extend" flag is false, the string passed in may not be NULL, will not be grown, and is usable in the original place after return. The return value can be NULL to signify overflow. +Field width: decimal digits, or * +Precision: dot, followed by decimal digits or * +Length modifiers: h L l ll z +Conversion specifiers: n d o u x X p f e E g G % c s S T Y D M + Returns the possibly-new (if copy for growth or taint-handling was needed) string, not nul-terminated. */ @@ -1571,6 +1576,14 @@ while (*fp) slen = string_datestamp_length; goto INSERT_STRING; + case 'Y': /* gstring pointer */ + { + gstring * zg = va_arg(ap, gstring *); + s = CS zg->s; + slen = zg->ptr; + goto INSERT_GSTRING; + } + case 's': case 'S': /* Forces *lower* case */ case 'T': /* Forces *upper* case */ @@ -1579,6 +1592,8 @@ while (*fp) if (!s) s = null; slen = Ustrlen(s); + INSERT_GSTRING: /* Coome to from %Y above */ + if (!(flags & SVFMT_TAINT_NOCHK) && is_incompatible(g->s, s)) if (flags & SVFMT_REBUFFER) { diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c index 76176a64e..c3e2d98e8 100644 --- a/src/src/tls-gnu.c +++ b/src/src/tls-gnu.c @@ -1135,7 +1135,7 @@ switch (tls_id) DEBUG(D_tls) debug_printf("\n"); if (server_seen_alpn > 1) { - log_write(0, LOG_MAIN, "TLS ALPN (%s) rejected", string_from_gstring(g)); + log_write(0, LOG_MAIN, "TLS ALPN (%Y) rejected", g); DEBUG(D_tls) debug_printf("TLS: too many ALPNs presented in handshake\n"); return GNUTLS_E_NO_APPLICATION_PROTOCOL; } diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c index cd715cc18..22c8ea99a 100644 --- a/src/src/tls-openssl.c +++ b/src/src/tls-openssl.c @@ -2404,7 +2404,7 @@ for (int pos = 0, siz; pos < inlen; pos += siz+1) if (pos + 1 + siz > inlen) siz = inlen - pos - 1; g = string_append_listele_n(g, ':', in + pos + 1, siz); } -log_write(0, LOG_MAIN, "TLS ALPN (%s) rejected", string_from_gstring(g)); +log_write(0, LOG_MAIN, "TLS ALPN (%Y) rejected", g); gstring_release_unused(g); return SSL_TLSEXT_ERR_ALERT_FATAL; } diff --git a/src/src/transports/lmtp.c b/src/src/transports/lmtp.c index e04c991ab..776c40e05 100644 --- a/src/src/transports/lmtp.c +++ b/src/src/transports/lmtp.c @@ -241,7 +241,7 @@ if (!string_vformat(&gs, SVFMT_TAINT_NOCHK, CS format, ap)) return FALSE; } va_end(ap); -DEBUG(D_transport|D_v) debug_printf(" LMTP>> %s", string_from_gstring(&gs)); +DEBUG(D_transport|D_v) debug_printf(" LMTP>> %Y", &gs); rc = write(fd, gs.s, gs.ptr); gs.ptr -= 2; string_from_gstring(&gs); /* remove \r\n for debug and error message */ if (rc > 0) return TRUE; diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c index 926e77df4..c502d7365 100644 --- a/src/src/transports/smtp.c +++ b/src/src/transports/smtp.c @@ -626,8 +626,8 @@ if (suffix) else message = string_fmt_append(message, " %s", exim_errstr(basic_errno)); -log_write(0, LOG_MAIN, "%s", string_from_gstring(message)); -deliver_msglog("%s %s\n", tod_stamp(tod_log), message->s); +log_write(0, LOG_MAIN, "%Y", message); +deliver_msglog("%s %.*s\n", tod_stamp(tod_log), message->ptr, message->s); } static void