| Summary: | sendmail: mci.c: bad pointer conversion in debug print | ||
|---|---|---|---|
| Product: | Base System | Reporter: | Valentin Nechayev <netch> |
| Component: | bin | Assignee: | Gregory Neil Shapiro <gshapiro> |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | ||
| Priority: | Normal | ||
| Version: | 3.3-STABLE | ||
| Hardware: | Any | ||
| OS: | Any | ||
> The following piece of mci_dump() uses bad conversion: > > snprintf(p, SPACELEFT(buf, p), "MCI@%lx: ", > sizeof(void *) == sizeof(u_long) ? > (u_long)(void *)mci : (u_long)(u_int)(void *)mci); > > On Alpha architecture, conversion from void* to u_int loses significant bits. On FreeBSD-alpha sizeof(void *) == sizeof(long), so the conversion from void * to u_int is never executed. Unfortunately, gcc apparently warns about casts from pointers to integers of a different size even in dead code. On FreeBSD_i386-with-64-bit-longs, gcc warns about the dead code in the other arm of the if and about 3 casts from pointers to u_longs. All these problems can be fixed better now by casting pointers to (u_long)(uintptr_t)(void *) and printing them with %lx, or if the format doesn't matter, by casting pointers to (void *) and printing them with %p. > These conversions are FreeBSD-specific; original Allman's sendmail > does not contain them. The original code was broken at runtime (it shows only the low 32 bits of pointers on FreeBSD-alpha). Bruce Bruce Evans <bde@zeta.org.au> wrote: > On FreeBSD-alpha sizeof(void *) == sizeof(long), so the conversion from > void * to u_int is never executed. Unfortunately, gcc apparently warns > about casts from pointers to integers of a different size even in dead > code. > > On FreeBSD_i386-with-64-bit-longs, gcc warns about the dead code in the > other arm of the if and about 3 casts from pointers to u_longs. All these > problems can be fixed better now by casting pointers to > (u_long)(uintptr_t)(void *) and printing them with %lx, or if the format > doesn't matter, by casting pointers to (void *) and printing them with %p. Well, shall it be better to use only %p and casting to void*, as "the only really right and portable way"? > > These conversions are FreeBSD-specific; original Allman's sendmail > > does not contain them. > > The original code was broken at runtime (it shows only the low 32 bits of > pointers on FreeBSD-alpha). Of course, original code is broken also and really. Do you know the reason of using integral formats instead of %p in original code? On Wed, 6 Oct 1999, Valentin Nechayev wrote: > Bruce Evans <bde@zeta.org.au> wrote: > > ... All these > > problems can be fixed better now by casting pointers to > > (u_long)(uintptr_t)(void *) and printing them with %lx, or if the format > > doesn't matter, by casting pointers to (void *) and printing them with %p. Except uintptr_t is not supported in RELENG_3. > > The original code was broken at runtime (it shows only the low 32 bits of > > pointers on FreeBSD-alpha). > > Of course, original code is broken also and really. Do you know the reason > of using integral formats instead of %p in original code? It's probably "portability". Some systems don't/didn't have %p. Bruce Responsible Changed From-To: freebsd-bugs->gshapiro Assigned to sendmail maintainer. State Changed
From-To: open->analyzed
I don't understand why FreeBSD has a different version of code for that.
The original sendmail code appears to be better for this case unless I am
missing something. I tried a test. Give try.c:
#include <sys/stat.h>
#include <sys/types.h>
#include <stdio.h>
int
main(int argc, char **argv)
{
struct stat b;
struct stat *a;
a = &b;
printf(" no cast: %lxn", a);
printf("sendmail: %lxn", (u_long) a);
printf(" FreeBSD: %lxn",
sizeof(void *) == sizeof(u_long) ?
(u_long)(void *)a : (u_long)(u_int)(void *)a);
}
Compiling on beast.freebsd.org gives a warning on the FreeBSD case:
> cc -mcpu=ev56 -O -pipe try.c -o try
try.c: In function `main':
try.c:16: warning: cast from pointer to integer of different size
But all three cases give the same result:
> ./try
no cast: 11ffb7e8
sendmail: 11ffb7e8
FreeBSD: 11ffb7e8
Unless I am mistaken, the FreeBSD modifications should be removed.
State Changed From-To: analyzed->feedback Return to the code as distributed by sendmail.org. This eliminates a warning on Alphas. It is still not the perfect solution for machines which sizeof(u_long) != sizeof(void *) but it is as close as we are going to get for now and consistent with the rest of the code. 8.12 has solved this problem by providing a portable snprintf() which understands %p. Unless I hear otherwise, I'll close this PR in the near future. State Changed From-To: feedback->closed The changes are now also in RELENG_4 (-STABLE). |
The following piece of mci_dump() uses bad conversion: snprintf(p, SPACELEFT(buf, p), "MCI@%lx: ", sizeof(void *) == sizeof(u_long) ? (u_long)(void *)mci : (u_long)(u_int)(void *)mci); On Alpha architecture, conversion from void* to u_int loses significant bits. These conversions are FreeBSD-specific; original Allman's sendmail does not contain them. Fix: Convert to ptrdiff_t instead of u_int (?) How-To-Repeat: Read and compile the code ;)