]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.9-20231012
authorWietse Venema <wietse@porcupine.org>
Thu, 12 Oct 2023 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <ietf-dane@dukhovni.org>
Sat, 14 Oct 2023 06:40:25 +0000 (02:40 -0400)
27 files changed:
postfix/HISTORY
postfix/proto/stop
postfix/proto/stop.double-history
postfix/proto/stop.spell-cc
postfix/src/bounce/bounce_notify_util.c
postfix/src/cleanup/cleanup_addr.c
postfix/src/global/dict_ldap.c
postfix/src/global/dict_mysql.c
postfix/src/global/dict_pgsql.c
postfix/src/global/dict_sqlite.c
postfix/src/global/mail_version.h
postfix/src/oqmgr/qmgr_deliver.c
postfix/src/postalias/postalias.c
postfix/src/postmap/postmap.c
postfix/src/postscreen/postscreen_smtpd.c
postfix/src/qmgr/qmgr_deliver.c
postfix/src/smtpd/smtpd.c
postfix/src/smtpd/smtpd_check.c
postfix/src/trivial-rewrite/resolve.c
postfix/src/util/casefold.c
postfix/src/util/dict_inline.c
postfix/src/util/dict_thash.c
postfix/src/util/dict_utf8.c
postfix/src/util/midna_domain.c
postfix/src/util/printable.c
postfix/src/util/stringops.h
postfix/src/util/valid_utf8_string.c

index a41360de9d4933518a90d622bea95e58e84b74fa..fbd6ea037f8ccdce1a56785cc1addae98d9a1b89 100644 (file)
@@ -27471,3 +27471,23 @@ Apologies for any names omitted.
 
        Cleanup: finer-grained unit tests for valid_utf8_string().
        File: util/valid_utf8_string.c.
+
+       Style: converted failed test reports to "got before want"
+       order, and converted tests to "fail before pass" order.
+       Files: util/valid_utf8_string.c, util/printable.c.
+
+       Cleanup: added a valid_utf8_stringz() function to simplify
+       most calls to validate null-terminated strings, eliminating
+       the runtime cost and code maintenance cost of 17 strlen()
+       calls. Files: src/bounce/bounce_notify_util.c,
+       src/cleanup/cleanup_addr.c, src/global/dict_ldap.c,
+       src/global/dict_mysql.c, src/global/dict_pgsql.c,
+       src/global/dict_sqlite.c, src/oqmgr/qmgr_deliver.c,
+       src/postalias/postalias.c, src/postmap/postmap.c,
+       src/postscreen/postscreen_smtpd.c, src/qmgr/qmgr_deliver.c,
+       src/smtpd/smtpd.c, src/smtpd/smtpd_check.c,
+       src/trivial-rewrite/resolve.c, src/util/casefold.c,
+       src/util/dict_inline.c, src/util/dict_thash.c,
+       src/util/dict_utf8.c, src/util/midna_domain.c,
+       src/util/printable.c, src/util/stringops.h,
+       src/util/valid_utf8_string.c.
index 2c5d841bdbd0ba604c764f525e77e250e53b654e..a7d43147401c79d4d0eef6c3aa16857ae46d99d3 100644 (file)
@@ -1586,3 +1586,4 @@ pubout
 rpk
 sni
 Amawalk
+resychronization
index 70f3971720a8498101a90944cccfaa610c3a2885..5767fcd57af8a0f17e58baa59c1029d11469fab5 100644 (file)
@@ -69,3 +69,6 @@ proto  proto aliases proto virtual proto ADDRESS_REWRITING_README html
  smtpd smtpd c 
  proto postconf proto postscreen postscreen c 
  global maillog_client c master master c smtp smtp c 
+ src postalias postalias c src postmap postmap c 
+ src postalias postalias c src postmap postmap c 
+ src smtpd smtpd c src smtpd smtpd_check c 
index 537b8a683b7c4a48402da000e291350b7d25c1d6..df4b069b8a27803aec2b757aa2945ed5f5cb7ba2 100644 (file)
@@ -1811,3 +1811,4 @@ peerpkey
 rpk
 ep
 inlined
+stringz
index 781a5257f95dfd61a36a239695ece210b9d8fb98..2482359545e1f0240425f7cbe2f4b9fdec54fbf0 100644 (file)
@@ -773,15 +773,14 @@ int     bounce_header_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
     post_mail_fprintf(bounce, "X-%s-Queue-ID: %s",
                      bounce_info->mail_name, bounce_info->queue_id);
 
-#define IS_UTF8_ADDRESS(str, len) \
-       ((str)[0] != 0 && !allascii(str) && valid_utf8_string((str), (len)))
+#define IS_UTF8_ADDRESS(str) \
+       ((str)[0] != 0 && !allascii(str) && valid_utf8_stringz(str))
 
     /* Fix 20140708: use "utf-8" or "rfc822" as appropriate. */
     if (VSTRING_LEN(bounce_info->sender) > 0)
        post_mail_fprintf(bounce, "X-%s-Sender: %s; %s",
                          bounce_info->mail_name, bounce_info->smtputf8
-                         && IS_UTF8_ADDRESS(STR(bounce_info->sender),
-                                        VSTRING_LEN(bounce_info->sender)) ?
+                         && IS_UTF8_ADDRESS(STR(bounce_info->sender)) ?
                          "utf-8" : "rfc822", STR(bounce_info->sender));
     if (bounce_info->arrival_time > 0)
        post_mail_fprintf(bounce, "Arrival-Date: %s",
@@ -800,8 +799,7 @@ int     bounce_recipient_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
     /* Fix 20140708: Don't send "utf-8" type with non-UTF8 address. */
     post_mail_fprintf(bounce, "Final-Recipient: %s; %s",
                      bounce_info->smtputf8
-                     && IS_UTF8_ADDRESS(rcpt->address,
-                                        strlen(rcpt->address)) ?
+                     && IS_UTF8_ADDRESS(rcpt->address) ?
                      "utf-8" : "rfc822", rcpt->address);
 
     /*
@@ -829,8 +827,7 @@ int     bounce_recipient_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
        /* Fix 20140708: Don't send "utf-8" type with non-UTF8 address. */
        post_mail_fprintf(bounce, "Original-Recipient: %s; %s",
                          bounce_info->smtputf8
-                         && IS_UTF8_ADDRESS(rcpt->orig_addr,
-                                            strlen(rcpt->orig_addr)) ?
+                         && IS_UTF8_ADDRESS(rcpt->orig_addr) ?
                          "utf-8" : "rfc822", rcpt->orig_addr);
     }
     post_mail_fprintf(bounce, "Action: %s",
index fd8a5114864a26d121473fd157ab02cca3d02311..f5e7d914c41d8287bc4f299b7fd3f3b9d72b46ef 100644 (file)
@@ -148,7 +148,7 @@ off_t   cleanup_addr_sender(CLEANUP_STATE *state, const char *buf)
     }
     /* Fix 20140711: Auto-detect an UTF8 sender. */
     if (var_smtputf8_enable && *STR(clean_addr) && !allascii(STR(clean_addr))
-       && valid_utf8_string(STR(clean_addr), LEN(clean_addr))) {
+       && valid_utf8_stringz(STR(clean_addr))) {
        state->smtputf8 |= SMTPUTF8_FLAG_SENDER;
        /* Fix 20140713: request SMTPUTF8 support selectively. */
        if (state->flags & CLEANUP_FLAG_AUTOUTF8)
@@ -216,7 +216,7 @@ void    cleanup_addr_recipient(CLEANUP_STATE *state, const char *buf)
     }
     /* Fix 20140711: Auto-detect an UTF8 recipient. */
     if (var_smtputf8_enable && *STR(clean_addr) && !allascii(STR(clean_addr))
-       && valid_utf8_string(STR(clean_addr), LEN(clean_addr))) {
+       && valid_utf8_stringz(STR(clean_addr))) {
        /* Fix 20140713: request SMTPUTF8 support selectively. */
        if (state->flags & CLEANUP_FLAG_AUTOUTF8)
            state->smtputf8 |= SMTPUTF8_FLAG_REQUESTED;
@@ -275,7 +275,7 @@ void    cleanup_addr_bcc_dsn(CLEANUP_STATE *state, const char *bcc,
     }
     /* Fix 20140711: Auto-detect an UTF8 recipient. */
     if (var_smtputf8_enable && *STR(clean_addr) && !allascii(STR(clean_addr))
-       && valid_utf8_string(STR(clean_addr), LEN(clean_addr))) {
+       && valid_utf8_stringz(STR(clean_addr))) {
        /* Fix 20140713: request SMTPUTF8 support selectively. */
        if (state->flags & CLEANUP_FLAG_AUTOUTF8)
            state->smtputf8 |= SMTPUTF8_FLAG_REQUESTED;
index a078721a84d2cdbb3815218a38056b898e9da3a7..7310a96618f94ed5641309b257e5ffe306120b12 100644 (file)
@@ -904,7 +904,7 @@ static int attrdesc_subtype(const char *a1, const char *a2)
 
 /* url_attrs - attributes we want from LDAP URL */
 
-static char **url_attrs(DICT_LDAP *dict_ldap, LDAPURLDesc * url)
+static char **url_attrs(DICT_LDAP *dict_ldap, LDAPURLDesc *url)
 {
     static ARGV *attrs;
     char  **a1;
@@ -1234,7 +1234,7 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name)
      * Don't frustrate future attempts to make Postfix UTF-8 transparent.
      */
     if ((dict->flags & DICT_FLAG_UTF8_ACTIVE) == 0
-       && !valid_utf8_string(name, strlen(name))) {
+       && !valid_utf8_stringz(name)) {
        if (msg_verbose)
            msg_info("%s: %s: Skipping lookup of non-UTF-8 key '%s'",
                     myname, dict_ldap->parser->name, name);
index bf4c2a848e30db144e139e41280faf8a6739bbb7..9f7d5409d4ca4cc9e072ac72f06851edec79d121 100644 (file)
@@ -251,7 +251,7 @@ static const char *dict_mysql_lookup(DICT *dict, const char *name)
      */
 #ifdef SNAPSHOT
     if ((dict->flags & DICT_FLAG_UTF8_ACTIVE) == 0
-       && !valid_utf8_string(name, strlen(name))) {
+       && !valid_utf8_stringz(name)) {
        if (msg_verbose)
            msg_info("%s: %s: Skipping lookup of non-UTF-8 key '%s'",
                     myname, dict_mysql->parser->name, name);
index ac1123e01b9bb22b5443d9a3647611827a4d56fa..787c410c27328ab5db59d74d3ee00610caa3805f 100644 (file)
@@ -279,7 +279,7 @@ static const char *dict_pgsql_lookup(DICT *dict, const char *name)
      */
 #ifdef SNAPSHOT
     if ((dict->flags & DICT_FLAG_UTF8_ACTIVE) == 0
-       && !valid_utf8_string(name, strlen(name))) {
+       && !valid_utf8_stringz(name)) {
        if (msg_verbose)
            msg_info("%s: %s: Skipping lookup of non-UTF-8 key '%s'",
                     myname, dict_pgsql->parser->name, name);
index 677d05ac2fc096f3a13fabee2d048753c1d8bc9d..7d6608a662e6c1ac16a506b0237c099fa9037c85 100644 (file)
@@ -149,7 +149,7 @@ static const char *dict_sqlite_lookup(DICT *dict, const char *name)
      * Don't frustrate future attempts to make Postfix UTF-8 transparent.
      */
     if ((dict->flags & DICT_FLAG_UTF8_ACTIVE) == 0
-       && !valid_utf8_string(name, strlen(name))) {
+       && !valid_utf8_stringz(name)) {
        if (msg_verbose)
            msg_info("%s: %s: Skipping lookup of non-UTF-8 key '%s'",
                     myname, dict_sqlite->parser->name, name);
index 249e5576d804d5b61b3c373a9d2ec9bf00a1914b..1a5567833f3c0e3a983ebc19fd18c1775b4fc90f 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20231011"
+#define MAIL_RELEASE_DATE      "20231012"
 #define MAIL_VERSION_NUMBER    "3.9"
 
 #ifdef SNAPSHOT
index 100ccc73dd824659065988e6a604799176ea20f2..9be6963aa325e4ac5ed31076d9c8ef26f191d4c5 100644 (file)
@@ -155,7 +155,7 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
      */
     for (recipient = list.info; recipient < list.info + list.len; recipient++)
        if (var_smtputf8_enable && (addr = recipient->address)[0]
-           && !allascii(addr) && valid_utf8_string(addr, strlen(addr))) {
+           && !allascii(addr) && valid_utf8_stringz(addr)) {
            smtputf8 |= SMTPUTF8_FLAG_RECIPIENT;
            if (message->verp_delims)
                smtputf8 |= SMTPUTF8_FLAG_SENDER;
index d17e397de4847a74506557c3ba50f35883f3a08b..72ca729988923bf9ea26d5396592d58a5f4881b0 100644 (file)
@@ -393,7 +393,7 @@ static void postalias(char *map_type, char *path_name, int postalias_flags,
             */
            if ((mkmap->dict->flags & DICT_FLAG_UTF8_ACTIVE)
                && !allascii(STR(line_buffer))
-               && !valid_utf8_string(STR(line_buffer), LEN(line_buffer))) {
+               && !valid_utf8_stringz(STR(line_buffer))) {
                msg_warn("%s, line %d: non-UTF-8 input \"%s\""
                         " -- ignoring this line",
                         VSTREAM_PATH(source_fp), lineno, STR(line_buffer));
index 2826fc6b62db47a9ed98540efdfbe85b33bf0880..739045081713c9a5a5999baa47bfe869afd29a4e 100644 (file)
@@ -489,7 +489,7 @@ static void postmap(char *map_type, char *path_name, int postmap_flags,
             */
            if ((mkmap->dict->flags & DICT_FLAG_UTF8_ACTIVE)
                && !allascii(STR(line_buffer))
-               && !valid_utf8_string(STR(line_buffer), LEN(line_buffer))) {
+               && !valid_utf8_stringz(STR(line_buffer))) {
                msg_warn("%s, line %d: non-UTF-8 input \"%s\""
                         " -- ignoring this line",
                         VSTREAM_PATH(source_fp), lineno, STR(line_buffer));
index dfc5d544a86cddce77bd358b35aa2c24489bea8a..1e859acc9fc49f6b81be059f3eb524f287fd768e 100644 (file)
@@ -874,7 +874,8 @@ static void psc_smtpd_read_event(int event, void *context)
            }
 
            /*
-            * Bare newline test.
+            * Bare newline test. Note: at this point, state->cmd_buffer is
+            * not null-terminated and may contain embedded null bytes.
             */
            if (ch == '\n') {
                if ((state->flags & PSC_STATE_MASK_BARLF_TODO_SKIP)
@@ -931,16 +932,15 @@ static void psc_smtpd_read_event(int event, void *context)
        /*
         * Avoid complaints from Postfix maps about malformed content.
         */
-#define PSC_BAD_UTF8(str, len) \
-       (var_smtputf8_enable && !valid_utf8_string((str), (len)))
+#define PSC_BAD_UTF8(str) \
+       (var_smtputf8_enable && !valid_utf8_stringz(str))
 
        /*
         * Terminate the command buffer, and apply the last-resort command
         * editing workaround.
         */
        VSTRING_TERMINATE(state->cmd_buffer);
-       if (psc_cmd_filter != 0 && !PSC_BAD_UTF8(STR(state->cmd_buffer),
-                                                LEN(state->cmd_buffer))) {
+       if (psc_cmd_filter != 0 && !PSC_BAD_UTF8(STR(state->cmd_buffer))) {
            const char *cp;
 
            for (cp = STR(state->cmd_buffer); *cp && IS_SPACE_TAB(*cp); cp++)
@@ -1007,7 +1007,7 @@ static void psc_smtpd_read_event(int event, void *context)
        if ((state->flags & PSC_STATE_MASK_NSMTP_TODO_SKIP)
            == PSC_STATE_FLAG_NSMTP_TODO && cmdp->name == 0
            && (is_header(command)
-               || PSC_BAD_UTF8(command, strlen(command))
+               || PSC_BAD_UTF8(command)
        /* Ignore forbid_cmds lookup errors. Non-critical feature. */
                || (*var_psc_forbid_cmds
                    && string_list_match(psc_forbid_cmds, command)))) {
index 07e89d448f788cadd306b3b68b4cedd5e48c2de5..441aed1f974e8ca7fb1391f65a58f663f2f1f5eb 100644 (file)
@@ -160,7 +160,7 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
      */
     for (recipient = list.info; recipient < list.info + list.len; recipient++)
        if (var_smtputf8_enable && (addr = recipient->address)[0]
-           && !allascii(addr) && valid_utf8_string(addr, strlen(addr))) {
+           && !allascii(addr) && valid_utf8_stringz(addr)) {
            smtputf8 |= SMTPUTF8_FLAG_RECIPIENT;
            if (message->verp_delims)
                smtputf8 |= SMTPUTF8_FLAG_SENDER;
index 8fb17905386909331a7b39862cfc8f8b0e560708..2dbc8350bcc289190a224804aac37a1df8b27e38 100644 (file)
@@ -5796,8 +5796,8 @@ static void smtpd_proto(SMTPD_STATE *state)
            watchdog_pat();
            smtpd_chat_query(state);
            /* Safety: protect internal interfaces against malformed UTF-8. */
-           if (var_smtputf8_enable && valid_utf8_string(STR(state->buffer),
-                                                LEN(state->buffer)) == 0) {
+           if (var_smtputf8_enable
+               && valid_utf8_stringz(STR(state->buffer)) == 0) {
                state->error_mask |= MAIL_ERROR_PROTOCOL;
                smtpd_chat_reply(state, "500 5.5.2 Error: bad UTF-8 syntax");
                state->error_count++;
index fd63f6813f24c35e87a0a64c1463dd02faf3e7c4..6ac617e4237b5cb452ce64b1364653cecf4350d8 100644 (file)
@@ -3267,7 +3267,7 @@ static int check_ccert_access(SMTPD_STATE *state, const char *acl_spec,
            if (result == SMTPD_CHECK_DUNNO)
                result = *respt;
            if (!var_smtpd_tls_enable_rpk
-               || *action == SMTPD_ACL_SEARCH_CODE_PKEY_FPRINT)
+               || *action == SMTPD_ACL_SEARCH_CODE_PKEY_FPRINT)
                break;
        }
     } else if (!var_smtpd_tls_ask_ccert) {
@@ -3281,7 +3281,7 @@ static int check_ccert_access(SMTPD_STATE *state, const char *acl_spec,
        && cert_result != SMTPD_CHECK_DUNNO
        && cert_result != pkey_result) {
        msg_warn("%s: %s: %s: Fragile access policy: %s=yes, but"
-                " the action for certificate fingerprint \"%s\" !="
+                " the action for certificate fingerprint \"%s\" !="
                 " the action for public key fingerprint \"%s\"",
                 myname, state->namaddr, acl->map_type_name,
                 VAR_SMTPD_TLS_ENABLE_RPK,
@@ -3997,7 +3997,7 @@ static int valid_utf8_action(const char *server, const char *action)
 {
     int     retval;
 
-    if ((retval = valid_utf8_string(action, strlen(action))) == 0)
+    if ((retval = valid_utf8_stringz(action)) == 0)
        msg_warn("malformed UTF-8 in policy server %s response: \"%s\"",
                 server, action);
     return (retval);
@@ -4053,6 +4053,7 @@ static int check_policy_service(SMTPD_STATE *state, const char *server,
     ENCODE_CN(issuer, issuer_buf, state->tls_context->issuer_CN);
 
 #define NONEMPTY(x) ((x) != 0 && (*x) != 0)
+
     /*
      * XXX: Too noisy to warn for each policy lookup, especially because we
      * don't even know whether the policy server will use the fingerprint. So
index 40e6aa5701e3c419021ab54c4425b07732cd0932..df761e76ceac85b18c5a75983695ddf8803f3f08 100644 (file)
@@ -427,7 +427,7 @@ static void resolve_addr(RES_CONTEXT *rp, char *sender, char *addr,
        if (!valid_mailhost_literal(rcpt_domain, DONT_GRIPE))
            *flags |= RESOLVE_FLAG_ERROR;
     } else if (var_smtputf8_enable
-              && valid_utf8_string(STR(nextrcpt), LEN(nextrcpt)) == 0) {
+              && valid_utf8_stringz(STR(nextrcpt)) == 0) {
        *flags |= RESOLVE_FLAG_ERROR;
     } else if (!valid_utf8_hostname(var_smtputf8_enable, rcpt_domain,
                                    DONT_GRIPE)) {
index d3ebd4b50a866de6be41136fac1e334b33c824cb..94860b8ecc34d167fb46b10a75a13c0d8528d50d 100644 (file)
@@ -300,7 +300,7 @@ int     main(int argc, char **argv)
                    encode_utf8(buffer, codepoint);
                    if (msg_verbose)
                        vstream_printf("U+%X -> %s\n", codepoint, STR(buffer));
-                   if (valid_utf8_string(STR(buffer), LEN(buffer)) == 0)
+                   if (valid_utf8_stringz(STR(buffer)) == 0)
                        msg_fatal("bad utf-8 encoding for U+%X\n", codepoint);
                    casefold(dest, STR(buffer));
                }
index 72339b2b2fbb681f2b49a26ec78c6a331f977e5c..d7f934466e05ed825d4be34a5b7f176d74cf2fe8 100644 (file)
@@ -87,7 +87,7 @@ DICT   *dict_inline_open(const char *name, int open_flags, int dict_flags)
      */
     if (DICT_NEED_UTF8_ACTIVATION(util_utf8_enable, dict_flags)
        && allascii(name) == 0
-       && valid_utf8_string(name, strlen(name)) == 0)
+       && valid_utf8_stringz(name) == 0)
        DICT_INLINE_RETURN(dict_surrogate(DICT_TYPE_INLINE, name,
                                          open_flags, dict_flags,
                                          "bad UTF-8 syntax: \"%s:%s\"; "
index 69eb17b6ff52f76378d1928aaaaf945646c63cb6..bae4a63746f53aed09337eedde8eab0b57cf7711 100644 (file)
@@ -127,7 +127,7 @@ DICT   *dict_thash_open(const char *path, int open_flags, int dict_flags)
             */
            if ((dict->flags & DICT_FLAG_UTF8_ACTIVE)
                && allascii(STR(line_buffer)) == 0
-           && valid_utf8_string(STR(line_buffer), LEN(line_buffer)) == 0) {
+               && valid_utf8_stringz(STR(line_buffer)) == 0) {
                msg_warn("%s, line %d: non-UTF-8 input \"%s\""
                         " -- ignoring this line",
                         VSTREAM_PATH(fp), lineno, STR(line_buffer));
@@ -181,8 +181,8 @@ DICT   *dict_thash_open(const char *path, int open_flags, int dict_flags)
                         " is this an alias file?", path, lineno);
 
            /*
-            * Optionally treat the value as a filename, and replace the value
-            * with the BASE64-encoded content of the named file.
+            * Optionally treat the value as a filename, and replace the
+            * value with the BASE64-encoded content of the named file.
             */
            if (dict_flags & DICT_FLAG_SRC_RHS_IS_FILE) {
                VSTRING *base64_buf;
index f1fc65a5920ccec21a47a04ac7f465093a19b57f..9bb6b7b8289fb5aaa7b168a32556573a753d1d8d 100644 (file)
@@ -100,7 +100,7 @@ static char *dict_utf8_check_fold(DICT *dict, const char *string,
     /*
      * Validate UTF-8 without casefolding.
      */
-    if (!allascii(string) && valid_utf8_string(string, strlen(string)) == 0) {
+    if (!allascii(string) && valid_utf8_stringz(string) == 0) {
        if (err)
            *err = "malformed UTF-8 or invalid codepoint";
        return (0);
@@ -123,7 +123,7 @@ static char *dict_utf8_check_fold(DICT *dict, const char *string,
 
 static int dict_utf8_check(const char *string, CONST_CHAR_STAR *err)
 {
-    if (!allascii(string) && valid_utf8_string(string, strlen(string)) == 0) {
+    if (!allascii(string) && valid_utf8_stringz(string) == 0) {
        if (err)
            *err = "malformed UTF-8 or invalid codepoint";
        return (0);
index 333a5c91d74819c10297ca7907e29bd556e881dc..bc016b637922692f6a1c7ce9d62e9463f2827472 100644 (file)
@@ -178,7 +178,7 @@ static void *midna_domain_to_ascii_create(const char *name, void *unused_context
     /*
      * Paranoia: do not expose uidna_*() to unfiltered network data.
      */
-    if (allascii(name) == 0 && valid_utf8_string(name, strlen(name)) == 0) {
+    if (allascii(name) == 0 && valid_utf8_stringz(name) == 0) {
        msg_warn("%s: Problem translating domain \"%.100s\" to ASCII form: %s",
                 myname, name, "malformed UTF-8");
        return (0);
@@ -232,7 +232,7 @@ static void *midna_domain_to_utf8_create(const char *name, void *unused_context)
     /*
      * Paranoia: do not expose uidna_*() to unfiltered network data.
      */
-    if (allascii(name) == 0 && valid_utf8_string(name, strlen(name)) == 0) {
+    if (allascii(name) == 0 && valid_utf8_stringz(name) == 0) {
        msg_warn("%s: Problem translating domain \"%.100s\" to UTF-8 form: %s",
                 myname, name, "malformed UTF-8");
        return (0);
index a30fe7b09f90be5d6d1714b4698fc193f90c8f1a..b944daa13b7ef7a9d233c8e01157e5b70d325161 100644 (file)
@@ -62,7 +62,7 @@
 #include "stringops.h"
 #include "parse_utf8_char.h"
 
-int util_utf8_enable = 0;
+int     util_utf8_enable = 0;
 
 /* printable -  binary compatibility */
 
@@ -119,6 +119,8 @@ char   *printable_except(char *string, int replacement, const char *except)
   * Test cases for 1-, 2-, and 3-byte encodings. Originally contributed by
   * Viktor Dukhovni, and annotated using translate.google.com.
   * 
+  * See valid_utf8_string.c for single-error tests.
+  * 
   * XXX Need a test for 4-byte encodings, preferably with strings that can be
   * displayed.
   */
@@ -201,16 +203,16 @@ int     main(int argc, char **argv)
        input = mystrdup(tp->input);
        actual = printable(input, '?');
 
-       if (strcmp(actual, tp->expected) == 0) {
-           vstream_fprintf(VSTREAM_ERR, "input: >%s<, want and got: >%s<\n",
+       if (strcmp(actual, tp->expected) != 0) {
+           vstream_fprintf(VSTREAM_ERR, "input: >%s<, got: >%s<, want: >%s<\n",
+                           tp->input, actual, tp->expected);
+           vstream_fprintf(VSTREAM_ERR, "FAIL %s\n", tp->name);
+           fail++;
+       } else {
+           vstream_fprintf(VSTREAM_ERR, "input: >%s<, got and want: >%s<\n",
                            tp->input, actual);
            vstream_fprintf(VSTREAM_ERR, "PASS %s\n", tp->name);
            pass++;
-       } else {
-           vstream_fprintf(VSTREAM_ERR, "input: >%s<, want: >%s<, got: >%s<\n",
-                           tp->input, tp->expected, actual);
-           vstream_fprintf(VSTREAM_ERR, "FAIL %s\n", tp->name);
-           fail++;
        }
        myfree(input);
     }
index 97aa597bea58f90042633899d2c297946a3d671e..ab38debbe0642b020e7d3fe13b4238a5fed1c960 100644 (file)
@@ -60,6 +60,7 @@ extern int allascii_len(const char *, ssize_t);
 extern const char *WARN_UNUSED_RESULT split_nameval(char *, char **, char **);
 extern const char *WARN_UNUSED_RESULT split_qnameval(char *, char **, char **);
 extern int valid_utf8_string(const char *, ssize_t);
+extern int valid_utf8_stringz(const char *);
 extern size_t balpar(const char *, const char *);
 extern char *WARN_UNUSED_RESULT extpar(char **, const char *, int);
 extern int strcasecmp_utf8x(int, const char *, const char *);
index 08b7e629c89b3266496cada72341a438fe0269a1..4cea0219b56a0d52b476365c71b72002432f5a5f 100644 (file)
@@ -9,11 +9,18 @@
 /*     int     valid_utf8_string(str, len)
 /*     const char *str;
 /*     ssize_t len;
+/*
+/*     int     valid_utf8_stringz(str)
+/*     const char *str;
+/*     ssize_t len;
 /* DESCRIPTION
 /*     valid_utf8_string() determines if all bytes in a string
 /*     satisfy parse_utf8_char(3h) checks. See there for any
 /*     implementation limitations.
 /*
+/*     valid_utf8_stringz() determines the same for zero-terminated
+/*     strings.
+/*
 /*     A zero-length string is considered valid.
 /* DIAGNOSTICS
 /*     The result value is zero when the caller specifies a negative
@@ -69,6 +76,27 @@ int     valid_utf8_string(const char *str, ssize_t len)
     return (1);
 }
 
+/* valid_utf8_stringz - validate string according to RFC 3629 */
+
+int     valid_utf8_stringz(const char *str)
+{
+    const char *cp;
+    const char *last;
+
+    /*
+     * Ideally, the compiler will inline parse_utf8_char(), propagate the
+     * null pointer constant value, and eliminate code branches that test
+     * whether 0 != 0.
+     */
+    for (cp = str; *cp; cp++) {
+       if ((last = parse_utf8_char(cp, 0)) != 0)
+           cp = last;
+       else
+           return (0);
+    }
+    return (1);
+}
+
  /*
   * Stand-alone test program. Each string is a line without line terminator.
   */
@@ -80,13 +108,13 @@ int     valid_utf8_string(const char *str, ssize_t len)
 #include <msg_vstream.h>
 
  /*
-  * Test cases for 1-, 2-, and 3-byte encodings. See printable() tests for
-  * provenance.
+  * Test cases for 1-, 2-, and 3-byte encodings. See printable.c for UTF8
+  * parser resychronization tests.
   * 
   * XXX Need a test for 4-byte encodings, preferably with strings that can be
   * displayed.
   * 
-  * XXX Need tests for over-long encodings and surrogates.
+  * XXX Need tests with hand-crafted over-long encodings and surrogates.
   */
 struct testcase {
     const char *name;
@@ -168,7 +196,8 @@ int     main(int argc, char **argv)
     util_utf8_enable = 1;
 
     for (pass = fail = 0, tp = testcases; tp < testcases + NUM_TESTS; tp++) {
-       int     actual;
+       int     actual_l;
+       int     actual_z;
 
        /*
         * Notes:
@@ -177,19 +206,28 @@ int     main(int argc, char **argv)
         * inputs and outputs. Use vstream_fprintf() instead.
         */
        vstream_fprintf(VSTREAM_ERR, "RUN  %s\n", tp->name);
-       actual = valid_utf8_string(tp->input, strlen(tp->input));
-
-       if (actual == tp->expected) {
-           vstream_fprintf(VSTREAM_ERR, "input: >%s<, want and got: >%s<\n",
-                           tp->input, valid_to_str(actual));
-           vstream_fprintf(VSTREAM_ERR, "PASS %s\n", tp->name);
-           pass++;
-       } else {
-           vstream_fprintf(VSTREAM_ERR, "input: >%s<, want: >%s<, got: >%s<\n",
-                           tp->input, valid_to_str(tp->expected),
-                           valid_to_str(actual));
+       actual_l = valid_utf8_string(tp->input, strlen(tp->input));
+       actual_z = valid_utf8_stringz(tp->input);
+
+       if (actual_l != tp->expected) {
+           vstream_fprintf(VSTREAM_ERR,
+                         "input: >%s<, 'actual_l' got: >%s<, want: >%s<\n",
+                           tp->input, valid_to_str(actual_l),
+                           valid_to_str(tp->expected));
+           vstream_fprintf(VSTREAM_ERR, "FAIL %s\n", tp->name);
+           fail++;
+       } else if (actual_z != tp->expected) {
+           vstream_fprintf(VSTREAM_ERR,
+                         "input: >%s<, 'actual_z' got: >%s<, want: >%s<\n",
+                           tp->input, valid_to_str(actual_z),
+                           valid_to_str(tp->expected));
            vstream_fprintf(VSTREAM_ERR, "FAIL %s\n", tp->name);
            fail++;
+       } else {
+           vstream_fprintf(VSTREAM_ERR, "input: >%s<, got and want: >%s<\n",
+                           tp->input, valid_to_str(actual_l));
+           vstream_fprintf(VSTREAM_ERR, "PASS %s\n", tp->name);
+           pass++;
        }
     }
     msg_info("PASS=%d FAIL=%d", pass, fail);