Subject: kern/9046: msdosfs can't read large (3.8gig) files
To: None <gnats-bugs@gnats.netbsd.org>
From: Martin J. Laubach <mjl@emsi.priv.at>
List: netbsd-bugs
Date: 12/23/1999 17:46:00
>Number: 9046
>Category: kern
>Synopsis: msdosfs can't read large (3.8gig) files
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kern-bug-people (Kernel Bug People)
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Thu Dec 23 17:45:01 1999
>Last-Modified:
>Originator: Martin J. Laubach
>Organization:
>Release: 19991210
>Environment:
System: NetBSD cactus.emsi.priv.at 1.4P NetBSD 1.4P (CACTUS) #0: Wed Dec 15 14:54:10 CET 1999 mjl@asparagus:/home/temp/devel/cvs/src/sys/arch/i386/compile/CACTUS i386
>Description:
This comes from FreeBSD PR kern/15639. The submitter is
unable to copy large files from an MS-DOS partition (test
case: a 3.8 G file).
Cross checking his fix with the NetBSD code base, the problem
is also present -- can someone with msdosfs knowledge please check
that this is the correct fix and commit it?
>How-To-Repeat:
>Fix:
-- From: Tim Kientzle <kientzle@acm.org> --
I've since found a fix for this problem. The bug
is in 'msdosfs_vnops.c', in the function
'msdosfs_read'.
Early in that function, it computes fileSize minus
requestedOffset, and stores the difference into a
signed int. With very large files, that int can
overflow. A better approach is to
make 'diff' an unsigned long, use a direct comparison
for the initial test, and then be cautious about comparing
'diff' to the signed 'n':
if (dep->de_FileSize <= uio->uio_offset)
return (0);
/* Note: diff can be as large as 4gig! */
diff = dep->de_FileSize - uio->uio_offset;
/* Avoid setting n to a negative value */
if ((diff < n) && (diff < LONG_MAX))
n = diff;
This change allowed me to successfully copy a 3.8gig file from
an MSDOS-formatted hard disk.
- Tim Kientzle
>Audit-Trail:
>Unformatted: