On 2004-10-30 02:26:31 +0200, Ulf Härnhammar wrote: > There are also a whole bunch of strncat() calls with the wrong > third parameter (it should be the number of characters left in > the string, not the whole size of the string). Thanks, too, for noting this one. I don't like the proposed fix, though, as it implies unnecessarily walking through the whole string twice. The attached patch (which is now going into the CVS) introduces new functions safe_strcat and safe_strncat that take a parameter that limits the destination's length; safe_strncat takes a second length parameter that limits the number of characters copied from the source. -- Thomas Roessler · Personal soap box at <http://log.does-not-exist.org/>.
Index: browser.c =================================================================== RCS file: /cvs/mutt/mutt/browser.c,v retrieving revision 3.10 diff -u -p -r3.10 browser.c --- browser.c 14 Jul 2004 05:45:18 -0000 3.10 +++ browser.c 30 Oct 2004 21:39:11 -0000 @@ -574,8 +574,8 @@ void _mutt_select_file (char *f, size_t else { getcwd (LastDir, sizeof (LastDir)); - strcat (LastDir, "/"); /* __STRCAT_CHECKED__ */ - strncat (LastDir, f, i); + safe_strcat (LastDir, sizeof (LastDir), "/"); + safe_strncat (LastDir, sizeof (LastDir), f, i); } } else Index: buffy.c =================================================================== RCS file: /cvs/mutt/mutt/buffy.c,v retrieving revision 3.9 diff -u -p -r3.9 buffy.c --- buffy.c 1 Feb 2004 17:50:43 -0000 3.9 +++ buffy.c 30 Oct 2004 21:39:12 -0000 @@ -439,7 +439,7 @@ int mutt_buffy_list (void) pos = 0; first = 1; buffylist[0] = 0; - pos += strlen (strncat (buffylist, _("New mail in "), sizeof (buffylist) - 1 - pos)); + pos += strlen (strncat (buffylist, _("New mail in "), sizeof (buffylist) - 1 - pos)); /* __STRNCAT_CHECKED__ */ for (tmp = Incoming; tmp; tmp = tmp->next) { /* Is there new mail in this mailbox? */ @@ -453,21 +453,21 @@ int mutt_buffy_list (void) break; if (!first) - pos += strlen (strncat(buffylist + pos, ", ", sizeof(buffylist)-1-pos)); + pos += strlen (strncat(buffylist + pos, ", ", sizeof(buffylist)-1-pos)); /* __STRNCAT_CHECKED__ */ /* Prepend an asterisk to mailboxes not already notified */ if (!tmp->notified) { - /* pos += strlen (strncat(buffylist + pos, "*", sizeof(buffylist)-1-pos)); */ + /* pos += strlen (strncat(buffylist + pos, "*", sizeof(buffylist)-1-pos)); __STRNCAT_CHECKED__ */ tmp->notified = 1; BuffyNotify--; } - pos += strlen (strncat(buffylist + pos, path, sizeof(buffylist)-1-pos)); + pos += strlen (strncat(buffylist + pos, path, sizeof(buffylist)-1-pos)); /* __STRNCAT_CHECKED__ */ first = 0; } if (!first && tmp) { - strncat (buffylist + pos, ", ...", sizeof (buffylist) - 1 - pos); + strncat (buffylist + pos, ", ...", sizeof (buffylist) - 1 - pos); /* __STRNCAT_CHECKED__ */ } if (!first) { Index: check_sec.sh =================================================================== RCS file: /cvs/mutt/mutt/check_sec.sh,v retrieving revision 3.1 diff -u -p -r3.1 check_sec.sh --- check_sec.sh 1 May 2002 23:20:56 -0000 3.1 +++ check_sec.sh 30 Oct 2004 21:39:12 -0000 @@ -34,6 +34,7 @@ do_check '\<fopen.*'\"'.*w' __FOPEN_CHEC do_check '\<(mutt_)?strcpy' __STRCPY_CHECKED__ "Alert: Unchecked strcpy calls." do_check '\<strcat' __STRCAT_CHECKED__ "Alert: Unchecked strcat calls." do_check '\<sprintf.*%s' __SPRINTF_CHECKED__ "Alert: Unchecked sprintf calls." +do_check '\<strncat' __STRNCAT_CHECKED__ "You probably meant safe_strcat here." # don't do this check on others' code. do_check_files '\<(malloc|realloc|free|strdup)[ ]*\(' __MEM_CHECKED__ "Alert: Use of traditional memory management calls." \ Index: commands.c =================================================================== RCS file: /cvs/mutt/mutt/commands.c,v retrieving revision 3.25 diff -u -p -r3.25 commands.c --- commands.c 14 Jul 2004 04:16:58 -0000 3.25 +++ commands.c 30 Oct 2004 21:39:15 -0000 @@ -282,10 +282,10 @@ void ci_bounce_message (HEADER *h, int * mutt_format_string (prompt, sizeof (prompt), 0, COLS-extra_space, 0, 0, prompt, sizeof (prompt), 0); - strncat (prompt, "...?", sizeof (prompt)); + safe_strcat (prompt, sizeof (prompt), "...?"); } else - strncat (prompt, "?", sizeof (prompt)); + safe_strcat (prompt, sizeof (prompt), "?"); if (query_quadoption (OPT_BOUNCE, prompt) != M_YES) { Index: edit.c =================================================================== RCS file: /cvs/mutt/mutt/edit.c,v retrieving revision 3.3 diff -u -p -r3.3 edit.c --- edit.c 19 Sep 2003 13:03:25 -0000 3.3 +++ edit.c 30 Oct 2004 21:39:16 -0000 @@ -463,7 +463,7 @@ int mutt_builtin_editor (const char *pat done = 1; else { - strncat (tmp, "\n", sizeof(tmp)); tmp[sizeof(tmp) - 1] = '\0'; + safe_strcat (tmp, sizeof (tmp), "\n"); if (buflen == bufmax) safe_realloc (&buf, sizeof (char *) * (bufmax += 25)); buf[buflen++] = safe_strdup (tmp[1] == '~' ? tmp + 1 : tmp); Index: lib.c =================================================================== RCS file: /cvs/mutt/mutt/lib.c,v retrieving revision 3.14 diff -u -p -r3.14 lib.c --- lib.c 29 Sep 2004 11:27:33 -0000 3.14 +++ lib.c 30 Oct 2004 21:39:17 -0000 @@ -153,6 +153,45 @@ char *safe_strdup (const char *s) return (p); } +char *safe_strcat (char *d, size_t l, const char *s) +{ + char *p = d; + + if (!l) + return d; + + l--; /* Space for the trailing '\0'. */ + + for (; *d && l; l--) + d++; + for (; *s && l; l--) + *d++ = *s++; + + *d = '\0'; + + return p; +} + +char *safe_strncat (char *d, size_t l, const char *s, size_t sl) +{ + char *p = d; + + if (!l) + return d; + + l--; /* Space for the trailing '\0'. */ + + for (; *d && l; l--) + d++; + for (; *s && l && sl; l--, sl--) + *d++ = *s++; + + *d = '\0'; + + return p; +} + + void mutt_str_replace (char **p, const char *s) { FREE (p); Index: lib.h =================================================================== RCS file: /cvs/mutt/mutt/lib.h,v retrieving revision 3.8 diff -u -p -r3.8 lib.h --- lib.h 4 Oct 2003 20:34:59 -0000 3.8 +++ lib.h 30 Oct 2004 21:39:17 -0000 @@ -115,6 +115,8 @@ char *mutt_skip_whitespace (char *); char *mutt_strlower (char *); char *mutt_substrcpy (char *, const char *, const char *, size_t); char *mutt_substrdup (const char *, const char *); +char *safe_strcat (char *, size_t, const char *); +char *safe_strncat (char *, size_t, const char *, size_t); char *safe_strdup (const char *); const char *mutt_stristr (const char *, const char *); Index: mutt_ssl.c =================================================================== RCS file: /cvs/mutt/mutt/mutt_ssl.c,v retrieving revision 3.4 diff -u -p -r3.4 mutt_ssl.c --- mutt_ssl.c 30 Aug 2004 20:05:40 -0000 3.4 +++ mutt_ssl.c 30 Oct 2004 21:39:19 -0000 @@ -417,7 +417,7 @@ static void x509_fingerprint (char *s, i { char ch[8]; snprintf (ch, 8, "%02X%s", md[j], (j % 2 ? " " : "")); - strncat (s, ch, l); + safe_strcat (s, l, ch); } } } @@ -629,9 +629,9 @@ static int ssl_check_certificate (sslsoc helpstr[0] = '\0'; mutt_make_help (buf, sizeof (buf), _("Exit "), MENU_GENERIC, OP_EXIT); - strncat (helpstr, buf, sizeof (helpstr)); + safe_strcat (helpstr, sizeof (helpstr), buf); mutt_make_help (buf, sizeof (buf), _("Help"), MENU_GENERIC, OP_HELP); - strncat (helpstr, buf, sizeof (helpstr)); + safe_strcat (helpstr, sizeof (helpstr), buf); menu->help = helpstr; done = 0; Index: muttlib.c =================================================================== RCS file: /cvs/mutt/mutt/muttlib.c,v retrieving revision 3.24 diff -u -p -r3.24 muttlib.c --- muttlib.c 30 Aug 2004 19:52:03 -0000 3.24 +++ muttlib.c 30 Oct 2004 21:39:21 -0000 @@ -815,8 +815,8 @@ void mutt_expand_fmt (char *dest, size_t if (!found && destlen > 0) { - strncat (dest, " ", destlen); - strncat (dest, src, destlen-1); + safe_strcat (dest, destlen, " "); + safe_strcat (dest, destlen, src); } } Index: recvcmd.c =================================================================== RCS file: /cvs/mutt/mutt/recvcmd.c,v retrieving revision 3.6 diff -u -p -r3.6 recvcmd.c --- recvcmd.c 9 Apr 2003 08:21:59 -0000 3.6 +++ recvcmd.c 30 Oct 2004 21:39:22 -0000 @@ -180,10 +180,10 @@ void mutt_attach_bounce (FILE * fp, HEAD mutt_format_string (prompt, sizeof (prompt) - 4, 0, COLS-extra_space, 0, 0, prompt, sizeof (prompt), 0); - strncat (prompt, "...?", sizeof (prompt)); + safe_strcat (prompt, sizeof (prompt), "...?"); } else - strncat (prompt, "?", sizeof (prompt)); + safe_strcat (prompt, sizeof (prompt), "?"); if (query_quadoption (OPT_BOUNCE, prompt) != M_YES) { Index: url.c =================================================================== RCS file: /cvs/mutt/mutt/url.c,v retrieving revision 3.5 diff -u -p -r3.5 url.c --- url.c 20 Jul 2004 08:17:21 -0000 3.5 +++ url.c 30 Oct 2004 21:39:24 -0000 @@ -166,8 +166,11 @@ int url_parse_ciss (ciss_url_t *ciss, ch } /* url_ciss_tostring: output the URL string for a given CISS object. */ + int url_ciss_tostring (ciss_url_t* ciss, char* dest, size_t len, int flags) { + size_t l; + if (ciss->scheme == U_UNKNOWN) return -1; @@ -175,25 +178,26 @@ int url_ciss_tostring (ciss_url_t* ciss, if (ciss->host) { - strncat (dest, "//", len - strlen (dest)); + safe_strcat (dest, len, "//"); + len -= (l = strlen (dest)); dest += l; + if (ciss->user) { if (flags & U_DECODE_PASSWD && ciss->pass) - snprintf (dest + strlen (dest), len - strlen (dest), "%s:%s@", - ciss->user, ciss->pass); + snprintf (dest, len, "%s:%s@", ciss->user, ciss->pass); else - snprintf (dest + strlen (dest), len - strlen (dest), "%s@", - ciss->user); + snprintf (dest, len, "%s@", ciss->user); + + len -= (l = strlen (dest)); dest += l; } if (ciss->port) - snprintf (dest + strlen (dest), len - strlen (dest), "%s:%hu/", - ciss->host, ciss->port); + snprintf (dest, len, "%s:%hu/", ciss->host, ciss->port); else - snprintf (dest + strlen (dest), len - strlen (dest), "%s/", ciss->host); + snprintf (dest, len, "%s/", ciss->host); } if (ciss->path) - strncat (dest, ciss->path, len - strlen (dest)); + safe_strcat (dest, len, ciss->path); return 0; } Index: imap/auth_cram.c =================================================================== RCS file: /cvs/mutt/mutt/imap/auth_cram.c,v retrieving revision 3.0 diff -u -p -r3.0 auth_cram.c --- imap/auth_cram.c 24 Jan 2002 13:35:57 -0000 3.0 +++ imap/auth_cram.c 30 Oct 2004 21:39:25 -0000 @@ -104,7 +104,7 @@ imap_auth_res_t imap_auth_cram_md5 (IMAP mutt_to_base64 ((unsigned char*) ibuf, (unsigned char*) obuf, strlen (obuf), sizeof (ibuf) - 2); - strncat (ibuf, "\r\n", sizeof (ibuf)); + safe_strcat (ibuf, sizeof (ibuf), "\r\n"); mutt_socket_write (idata->conn, ibuf); do Index: imap/auth_gss.c =================================================================== RCS file: /cvs/mutt/mutt/imap/auth_gss.c,v retrieving revision 3.1 diff -u -p -r3.1 auth_gss.c --- imap/auth_gss.c 12 Nov 2002 08:20:11 -0000 3.1 +++ imap/auth_gss.c 30 Oct 2004 21:39:25 -0000 @@ -122,7 +122,7 @@ imap_auth_res_t imap_auth_gss (IMAP_DATA mutt_to_base64 ((unsigned char*) buf1, send_token.value, send_token.length, sizeof (buf1) - 2); gss_release_buffer (&min_stat, &send_token); - strncat (buf1, "\r\n", sizeof (buf1)); + safe_strcat (buf1, sizeof (buf1), "\r\n"); mutt_socket_write (idata->conn, buf1); while (maj_stat == GSS_S_CONTINUE_NEEDED) @@ -158,7 +158,7 @@ imap_auth_res_t imap_auth_gss (IMAP_DATA mutt_to_base64 ((unsigned char*) buf1, send_token.value, send_token.length, sizeof (buf1) - 2); gss_release_buffer (&min_stat, &send_token); - strncat (buf1, "\r\n", sizeof (buf1)); + safe_strcat (buf1, sizeof (buf1), "\r\n"); mutt_socket_write (idata->conn, buf1); } @@ -226,7 +226,7 @@ imap_auth_res_t imap_auth_gss (IMAP_DATA sizeof (buf1) - 2); dprint (2, (debugfile, "Requesting authorisation as %s\n", idata->conn->account.user)); - strncat (buf1, "\r\n", sizeof (buf1)); + safe_strcat (buf1, sizeof (buf1), "\r\n"); mutt_socket_write (idata->conn, buf1); /* Joy of victory or agony of defeat? */ Index: imap/imap.c =================================================================== RCS file: /cvs/mutt/mutt/imap/imap.c,v retrieving revision 3.15 diff -u -p -r3.15 imap.c --- imap/imap.c 16 Aug 2004 21:36:38 -0000 3.15 +++ imap/imap.c 30 Oct 2004 21:39:29 -0000 @@ -791,7 +791,7 @@ static void imap_set_flag (IMAP_DATA* id { if (mutt_bit_isset (idata->rights, aclbit)) if (flag) - strncat (flags, str, flsize); + safe_strcat (flags, flsize, str); } /* imap_make_msg_set: make an IMAP4rev1 UID message set out of a set of Index: imap/message.c =================================================================== RCS file: /cvs/mutt/mutt/imap/message.c,v retrieving revision 3.9 diff -u -p -r3.9 message.c --- imap/message.c 22 Jul 2004 01:10:55 -0000 3.9 +++ imap/message.c 30 Oct 2004 21:39:30 -0000 @@ -663,8 +663,8 @@ void imap_add_keywords (char* s, HEADER* { if (msg_has_flag (mailbox_flags, keywords->data)) { - strncat (s, keywords->data, slen); - strncat (s, " ", slen); + safe_strcat (s, slen, keywords->data); + safe_strcat (s, slen, " "); } keywords = keywords->next; }
Attachment:
pgpLvlu30hqNt.pgp
Description: PGP signature