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