| Summary: | rcp -p fails when times have high bit set | ||
|---|---|---|---|
| Product: | Base System | Reporter: | klh <klh> |
| Component: | bin | Assignee: | Sheldon Hearn <sheldonh> |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | ||
| Priority: | Normal | ||
| Version: | Unspecified | ||
| Hardware: | Any | ||
| OS: | Any | ||
On Sat, 8 Jan 2000 klh@netcom.com wrote: > >Description: > This code fragment should be using %ul instead of %ld for both fields. > > if (pflag) { > (void)snprintf(path, sizeof(path), "T%ld 0 %ld 0\n", > (long)statp->st_mtimespec.tv_sec, > (long)statp->st_atimespec.tv_sec); > (void)write(rem, path, strlen(path)); Not under systems with signed time_t like FreeBSD. Using %ul would break times before the epoch (about 1970). > >How-To-Repeat: > Create a file with a st_mtime that has the high bit set. Attempt > to copy it with "rcp -p foo target:." > where target is a 64-bit system such as an Alpha (running D/U in this > case). Will fail with a "mtime.sec not delimited" screwup message > due to presence of a minus sign. This seems to be a defect in D/U :-). An st_mtime with the high bit set is negative. Negative times give undefined behaviour in POSIX.1. FreeBSD supports them, but actually using them gives interoperability problems like the one you noticed. > >Fix: Don't create files with an st_mtime that is before the epoch. Related bugs: FreeBSD's rcp.c lacks range checking of times sent by the target system. Large times are silently truncated to (time_t)LONG_MAX, i.e., to LONG_MAX on i386's and -1 on alphas. Large negative times are silently truncated to (time_t)LONG_MIN, i.e., to LONG_MIN on i386's and 0 on alphas. Bruce State Changed From-To: open->suspended Fixed in CURRENT's rev 1.9 of util.c: http://www.freebsd.org/cgi/cvsweb.cgi/src/usr.bin/ftp/util.c.diff?r1=1.8&r2=1.9 Only _critical_ bugfixes are merged into the STABLE branch immediately, so I'll leave this to simmer for a few weeks. Responsible Changed From-To: freebsd-bugs->sheldonh reminder for me to merge to STABLE. State Changed From-To: suspended->closed Merged onto the then-stable RELENG_3 branch on 2000-03-27. > Not under systems with signed time_t like FreeBSD. Using %ul would > break times before the epoch (about 1970). Sigh. OK, I didn't realize this was a conscious decision in FreeBSD. I assume there are good reasons for this (to me) surprising choice. If there is anything that explains the rationale, I would like to read about it. In particular, what's the plan for Jan 18, 2038? Thanks. > > >Fix: > > Don't create files with an st_mtime that is before the epoch. Well, the files in question are created by FreeBSD's user-FTP when retrieving them from a SunOS system, which responds to MDTM with "213 191000107192503". Looks like the old BSD ftp did something like printf("19%2d", t->tm_year). Should we: (a) do nothing and continue to get screwed, (b) test for negatives and substitute current time, (c) test for this case (eg by checking string length) and DWIM it, (d) convince Sun to fix their code (hahahahaha) ? --Ken |
This code fragment should be using %ul instead of %ld for both fields. if (pflag) { (void)snprintf(path, sizeof(path), "T%ld 0 %ld 0\n", (long)statp->st_mtimespec.tv_sec, (long)statp->st_atimespec.tv_sec); (void)write(rem, path, strlen(path)); How-To-Repeat: Create a file with a st_mtime that has the high bit set. Attempt to copy it with "rcp -p foo target:." where target is a 64-bit system such as an Alpha (running D/U in this case). Will fail with a "mtime.sec not delimited" screwup message due to presence of a minus sign. However, it should not be necessary to reproduce this to realize that the given code fragment is a time bomb, so to speak...