Module Name: src Committed By: christos Date: Mon Feb 7 17:36:42 UTC 2011
Modified Files: src/sbin/fsck_msdos: dir.c Log Message: PR/44529: Martin Danielsson: fsck_msdos crashes when verifying corrupt file system. Avoid using the long name index when it is 0. Refactor the code to avoid duplication. To generate a diff of this commit: cvs rdiff -u -r1.23 -r1.24 src/sbin/fsck_msdos/dir.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sbin/fsck_msdos/dir.c diff -u src/sbin/fsck_msdos/dir.c:1.23 src/sbin/fsck_msdos/dir.c:1.24 --- src/sbin/fsck_msdos/dir.c:1.23 Sat Apr 11 03:14:50 2009 +++ src/sbin/fsck_msdos/dir.c Mon Feb 7 12:36:42 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: dir.c,v 1.23 2009/04/11 07:14:50 lukem Exp $ */ +/* $NetBSD: dir.c,v 1.24 2011/02/07 17:36:42 christos Exp $ */ /* * Copyright (C) 1995, 1996, 1997 Wolfgang Solfrank @@ -30,7 +30,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: dir.c,v 1.23 2009/04/11 07:14:50 lukem Exp $"); +__RCSID("$NetBSD: dir.c,v 1.24 2011/02/07 17:36:42 christos Exp $"); #endif /* not lint */ #include <stdio.h> @@ -204,6 +204,7 @@ * Global variables temporarily used during a directory scan */ static char longName[DOSLONGNAMELEN] = ""; +static char *eLongName = longName + sizeof(longName); static u_char *buffer = NULL; static u_char *delbuf = NULL; @@ -432,6 +433,26 @@ return FSOK; } +static int +procName(int from, int to, char **dst, const u_char *src) +{ + int k; + char *t = *dst; + + for (k = from; k < to && t < eLongName; k += 2) { + if (!src[k] && !src[k + 1]) + break; + *t++ = src[k]; + /* + * Warn about those unusable chars in msdosfs here? XXX + */ + if (src[k + 1]) + t[-1] = '?'; + } + *dst = t; + return k; +} + /* * Read a directory and * - resolve long name records @@ -526,6 +547,7 @@ } if (p[11] == ATTR_WIN95) { + u_int lrnomask = *p & LRNOMASK; if (*p & LRFIRST) { if (shortSum != -1) { if (!invlfn) { @@ -538,7 +560,7 @@ vallfn = p; valcl = cl; } else if (shortSum != p[13] - || lidx != (*p & LRNOMASK)) { + || lidx != lrnomask || lrnomask != 0) { if (!invlfn) { invlfn = vallfn; invcl = valcl; @@ -549,52 +571,35 @@ } vallfn = NULL; } - lidx = *p & LRNOMASK; - t = longName + --lidx * 13; - for (k = 1; k < 11 && t < longName + sizeof(longName); k += 2) { - if (!p[k] && !p[k + 1]) - break; - *t++ = p[k]; - /* - * Warn about those unusable chars in msdosfs here? XXX - */ - if (p[k + 1]) - t[-1] = '?'; - } - if (k >= 11) - for (k = 14; k < 26 && t < longName + sizeof(longName); k += 2) { - if (!p[k] && !p[k + 1]) - break; - *t++ = p[k]; - if (p[k + 1]) - t[-1] = '?'; - } - if (k >= 26) - for (k = 28; k < 32 && t < longName + sizeof(longName); k += 2) { - if (!p[k] && !p[k + 1]) - break; - *t++ = p[k]; - if (p[k + 1]) - t[-1] = '?'; - } - if (t >= longName + sizeof(longName)) { - pwarn("long filename too long\n"); - if (!invlfn) { - invlfn = vallfn; - invcl = valcl; + lidx = lrnomask; + if (lidx != 0) { + t = longName + --lidx * 13; + k = procName(1, 11, &t, p); + if (k >= 11) + k = procName(14, 26, &t, p); + if (k >= 26) + k = procName(28, 32, &t, p); + if (t >= eLongName) { + pwarn( + "long filename too long\n"); + if (!invlfn) { + invlfn = vallfn; + invcl = valcl; + } + vallfn = NULL; } - vallfn = NULL; } if (p[26] | (p[27] << 8)) { - pwarn("long filename record cluster start != 0\n"); + pwarn("long filename record cluster " + "start != 0\n"); if (!invlfn) { invlfn = vallfn; invcl = cl; } vallfn = NULL; } - continue; /* long records don't carry further - * information */ + continue; /* long records don't carry + * further information */ } /*