i've finally tracked this down:
nmh code assumes strcasecmp accepts NULL arguments.
for portability reasons sbr/strcasecmp.c defines str[n]casecmp functions
which do accept NULL arguments.
/usr/include/string.h declares strcasecmp:
extern int strcasecmp (__const char *__s1, __const char *__s2)
__THROW __attribute_pure__ __nonnull ((1, 2));
when compiling sbr/strcasecmp.c with -O2 gcc respects that nonnull
declaration and eliminates the tests for NULL from the sbr/strcasecmp.c
code.
this results in the (somewhat arbitrary) segfaults we've been seeing.
there are two solutions. one is to compile with -O1 rather than -O2,
which disables whatever optimization is doing this (i've tried -O2
-fno-delete-null-pointer-checks but that still seems to delete the null
tests... perhaps i should bug gcc too).
the other option is the patch below. (i prefer this solution)
i'm also attaching a patch which is almost certainly necessary for 64-bit
portability: the difference of pointers is 64-bits yet the code is using
pointer diffs in many places where int (32-bits) are required.
-dean
Index: nmh-1.2/h/nmh.h
===================================================================
--- nmh-1.2.orig/h/nmh.h 2007-05-21 23:41:43.577421877 -0700
+++ nmh-1.2/h/nmh.h 2007-05-21 23:41:57.149076687 -0700
@@ -41,6 +41,8 @@
#if STDC_HEADERS || HAVE_STRING_H
# include <string.h>
+# define strcasecmp my_strcasecmp
+# define strncasecmp my_strncasecmp
/* An ANSI string.h and pre-ANSI memory.h might conflict. */
# if !STDC_HEADERS && HAVE_MEMORY_H
# include <memory.h>
Index: nmh-1.2/sbr/fmt_scan.c
===================================================================
--- nmh-1.2.orig/sbr/fmt_scan.c 2007-05-21 22:08:08.385987915 -0700
+++ nmh-1.2/sbr/fmt_scan.c 2007-05-21 22:09:51.159105255 -0700
@@ -255,7 +255,7 @@
|| !(cp = strchr(mbox += idx + strlen (key), '/')))
return 0;
- snprintf (buffer, buffer_len, "%*.*s", cp - mbox, cp - mbox, mbox);
+ snprintf (buffer, buffer_len, "%*.*s", (int)(cp - mbox), (int)(cp - mbox),
mbox);
return 1;
}
Index: nmh-1.2/sbr/lock_file.c
===================================================================
--- nmh-1.2.orig/sbr/lock_file.c 2007-05-21 22:10:02.210795073 -0700
+++ nmh-1.2/sbr/lock_file.c 2007-05-21 22:10:12.638502370 -0700
@@ -493,7 +493,7 @@
bplen += tmplen;
#else
if (cp != file) {
- snprintf (bp, sizeof(li->curlock), "%.*s", cp - file, file);
+ snprintf (bp, sizeof(li->curlock), "%.*s", (int)(cp - file), file);
tmplen = strlen (bp);
bp += tmplen;
bplen += tmplen;
Index: nmh-1.2/sbr/m_backup.c
===================================================================
--- nmh-1.2.orig/sbr/m_backup.c 2007-05-21 22:10:29.590026473 -0700
+++ nmh-1.2/sbr/m_backup.c 2007-05-21 22:10:40.141730200 -0700
@@ -22,7 +22,7 @@
snprintf(buffer, sizeof(buffer), "%s%s",
BACKUP_PREFIX, cp);
else
- snprintf(buffer, sizeof(buffer), "%.*s%s%s", cp - file, file,
+ snprintf(buffer, sizeof(buffer), "%.*s%s%s", (int)(cp - file), file,
BACKUP_PREFIX, cp);
unlink(buffer);
Index: nmh-1.2/sbr/m_getfld.c
===================================================================
--- nmh-1.2.orig/sbr/m_getfld.c 2007-05-21 22:11:09.316921446 -0700
+++ nmh-1.2/sbr/m_getfld.c 2007-05-21 22:11:29.072375827 -0700
@@ -699,10 +699,10 @@
if (cp) {
/* return path for UUCP style addressing */
dp = strchr (++cp, '\n');
- snprintf (rp, rplen, "%.*s!%.*s\n", dp - cp, cp, bp - ap, ap);
+ snprintf (rp, rplen, "%.*s!%.*s\n", (int)(dp - cp), cp, (int)(bp - ap),
ap);
} else {
/* return path for standard domain addressing */
- snprintf (rp, rplen, "%.*s\n", bp - ap, ap);
+ snprintf (rp, rplen, "%.*s\n", (int)(bp - ap), ap);
}
/*
Index: nmh-1.2/sbr/m_scratch.c
===================================================================
--- nmh-1.2.orig/sbr/m_scratch.c 2007-05-21 22:11:38.268121797 -0700
+++ nmh-1.2/sbr/m_scratch.c 2007-05-21 22:11:45.303927411 -0700
@@ -33,7 +33,7 @@
if ((cp = r1bindex (file, '/')) == file)
strncpy (buffer, tmpfil, sizeof(buffer));
else
- snprintf (buffer, sizeof(buffer), "%.*s%s", cp - file, file, tmpfil);
+ snprintf (buffer, sizeof(buffer), "%.*s%s", (int)(cp - file), file,
tmpfil);
unlink (buffer);
return buffer;
Index: nmh-1.2/sbr/mf.c
===================================================================
--- nmh-1.2.orig/sbr/mf.c 2007-05-21 22:12:24.410846588 -0700
+++ nmh-1.2/sbr/mf.c 2007-05-21 22:12:32.198631277 -0700
@@ -433,7 +433,7 @@
while (isspace (*ap))
ap++;
if (cp)
- sprintf (adr, "%.*s", cp - ap, ap);
+ sprintf (adr, "%.*s", (int)(cp - ap), ap);
else
strcpy (adr, ap);
bp = adr + strlen (adr) - 1;
Index: nmh-1.2/sbr/path.c
===================================================================
--- nmh-1.2.orig/sbr/path.c 2007-05-21 22:11:56.443619600 -0700
+++ nmh-1.2/sbr/path.c 2007-05-21 22:12:16.211073263 -0700
@@ -85,7 +85,7 @@
name += NCWD;
if (strcmp (name, DOTDOT) == 0 || strcmp (name, PWD) == 0) {
- snprintf (buffer, sizeof(buffer), "%.*s", cp - pwds, pwds);
+ snprintf (buffer, sizeof(buffer), "%.*s", (int)(cp - pwds), pwds);
return getcpy (buffer);
}
@@ -94,7 +94,7 @@
else
cp = ep;
- snprintf (buffer, sizeof(buffer), "%.*s/%s", cp - pwds, pwds, name);
+ snprintf (buffer, sizeof(buffer), "%.*s/%s", (int)(cp - pwds), pwds, name);
return getcpy (buffer);
}
Index: nmh-1.2/uip/annosbr.c
===================================================================
--- nmh-1.2.orig/uip/annosbr.c 2007-05-21 22:12:49.394155779 -0700
+++ nmh-1.2/uip/annosbr.c 2007-05-21 22:13:00.665844024 -0700
@@ -384,7 +384,7 @@
while (*cp && *cp++ != '\n')
continue;
if (cp - sp)
- fprintf (tmp, "%s: %*.*s", comp, cp - sp, cp - sp, sp);
+ fprintf (tmp, "%s: %*.*s", comp, (int)(cp - sp), (int)(cp -
sp), sp);
} while (*cp);
if (cp[-1] != '\n' && cp != text)
putc ('\n', tmp);
Index: nmh-1.2/uip/mhbuildsbr.c
===================================================================
--- nmh-1.2.orig/uip/mhbuildsbr.c 2007-05-21 22:13:25.841147532 -0700
+++ nmh-1.2/uip/mhbuildsbr.c 2007-05-21 22:13:44.884620511 -0700
@@ -4213,7 +4213,7 @@
while (*cp)
cp++;
fprintf (stderr, "invalid MD5 digest (got %d octets)\n",
- cp - bp);
+ (int)(cp - bp));
}
return NOTOK;
Index: nmh-1.2/uip/mhparse.c
===================================================================
--- nmh-1.2.orig/uip/mhparse.c 2007-05-21 22:13:55.160336074 -0700
+++ nmh-1.2/uip/mhparse.c 2007-05-21 22:14:01.720154472 -0700
@@ -2676,7 +2676,7 @@
while (*cp)
cp++;
fprintf (stderr, "invalid MD5 digest (got %d octets)\n",
- cp - bp);
+ (int)(cp - bp));
}
return NOTOK;
Index: nmh-1.2/uip/dropsbr.c
===================================================================
--- nmh-1.2.orig/uip/dropsbr.c 2007-05-21 22:14:17.055729856 -0700
+++ nmh-1.2/uip/dropsbr.c 2007-05-21 22:14:43.726991149 -0700
@@ -387,7 +387,7 @@
fp = strchr(ep + 1, '\n');
tp = dctime(dlocaltimenow());
snprintf (buffer, sizeof(buffer), "From %.*s %s",
- fp - ep, ep, tp);
+ (int)(fp - ep), ep, tp);
} else if (!strncmp (buffer, "X-Envelope-From:", 16)) {
/*
* Change the "X-Envelope-From:" field
@@ -499,10 +499,10 @@
if ((dp = strchr(cp = r1bindex (file, '/'), '.')) == NULL)
dp = cp + strlen (cp);
if (cp == file)
- snprintf (buffer, sizeof(buffer), ".%.*s%s", dp - cp, cp, ".map");
+ snprintf (buffer, sizeof(buffer), ".%.*s%s", (int)(dp - cp), cp,
".map");
else
snprintf (buffer, sizeof(buffer), "%.*s.%.*s%s",
- cp - file, file, dp - cp, cp, ".map");
+ (int)(cp - file), file, (int)(dp - cp), cp, ".map");
return buffer;
}
Index: nmh-1.2/uip/slocal.c
===================================================================
--- nmh-1.2.orig/uip/slocal.c 2007-05-21 22:14:51.174784819 -0700
+++ nmh-1.2/uip/slocal.c 2007-05-21 22:15:06.914348706 -0700
@@ -1372,11 +1372,11 @@
/* return path for UUCP style addressing */
ep = strchr(++hp, '\n');
snprintf (buffer, sizeof(buffer), "Return-Path:
%.*s!%.*s\n",
- ep - hp, hp, cp - fp, fp);
+ (int)(ep - hp), hp, (int)(cp - fp), fp);
} else {
/* return path for standard domain addressing */
snprintf (buffer, sizeof(buffer), "Return-Path: %.*s\n",
- cp - fp, fp);
+ (int)(cp - fp), fp);
}
/* Add Return-Path header to message */