On Thu, Sep 22, 2011 at 03:56:11PM +0100, Edd Barrett wrote:
> Hi,
> 
> An upstream of one of the ports I work on (radare2) has imported our file(1)
> implementation and claims to have found bugs. This is the first:
> 
> 'ms->file' will only be assigned to 'fn' after a call to apprentice_load() and
> ultimately load_1(), so the file_magwarn() at line 274 would report the 
> default
> filename "unknown".
> 
> We can trigger this behaviour by executing `file -c`:
> unknown, 0: Warning: using regular magic file `/etc/magic'
> 
> Is it a bug?
> 
> Index: apprentice.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/file/apprentice.c,v
> retrieving revision 1.29
> diff -u -r1.29 apprentice.c
> --- apprentice.c      11 Nov 2009 16:21:51 -0000      1.29
> +++ apprentice.c      22 Sep 2011 14:27:17 -0000
> @@ -258,6 +258,7 @@
>               return -1;
>       }
>  
> +     ms->file = fn;
>       if (action == FILE_COMPILE) {
>               rv = apprentice_load(ms, &magic, &nmagic, fn, action);
>               if (rv != 0)

Seems correct to me, but this "fn" seems kinda redundant down the
stack, except for load_1() which really needs a file and not a
directory. 

So I thought we could kill this fn by assigning ms->file right in the
beginning at file_apprentice(). Also tweak load_1() so it won't do the
whole processing in an else. 

Index: apprentice.c
===================================================================
RCS file: /cvs/src/usr.bin/file/apprentice.c,v
retrieving revision 1.29
diff -d -u -p -w -r1.29 apprentice.c
--- apprentice.c        11 Nov 2009 16:21:51 -0000      1.29
+++ apprentice.c        28 Sep 2011 03:18:29 -0000
@@ -96,11 +96,11 @@ private int parse(struct magic_set *, st
 private int parse_mime(struct magic_set *, struct magic_entry **, uint32_t *,
     const char *);
 private void eatsize(const char **);
-private int apprentice_1(struct magic_set *, const char *, int, struct mlist 
*);
+private int apprentice_1(struct magic_set *, int, struct mlist *);
 private size_t apprentice_magic_strength(const struct magic *);
 private int apprentice_sort(const void *, const void *);
 private int apprentice_load(struct magic_set *, struct magic **, uint32_t *,
-    const char *, int);
+    int);
 private void byteswap(struct magic *, uint32_t);
 private void bs1(struct magic *);
 private uint16_t swap2(uint16_t);
@@ -242,7 +242,7 @@ init_file_tables(void)
  * Handle one file or directory.
  */
 private int
-apprentice_1(struct magic_set *ms, const char *fn, int action,
+apprentice_1(struct magic_set *ms, int action,
     struct mlist *mlist)
 {
        struct magic *magic = NULL;
@@ -259,19 +259,19 @@ apprentice_1(struct magic_set *ms, const
        }
 
        if (action == FILE_COMPILE) {
-               rv = apprentice_load(ms, &magic, &nmagic, fn, action);
+               rv = apprentice_load(ms, &magic, &nmagic, action);
                if (rv != 0)
                        return -1;
-               rv = apprentice_compile(ms, &magic, &nmagic, fn);
+               rv = apprentice_compile(ms, &magic, &nmagic, ms->file);
                free(magic);
                return rv;
        }
 
 #ifndef COMPILE_ONLY
-       if ((rv = apprentice_map(ms, &magic, &nmagic, fn)) == -1) {
+       if ((rv = apprentice_map(ms, &magic, &nmagic, ms->file)) == -1) {
                if (ms->flags & MAGIC_CHECK)
-                       file_magwarn(ms, "using regular magic file `%s'", fn);
-               rv = apprentice_load(ms, &magic, &nmagic, fn, action);
+                       file_magwarn(ms, "using regular magic file `%s'", 
ms->file);
+               rv = apprentice_load(ms, &magic, &nmagic, action);
                if (rv != 0)
                        return -1;
        }
@@ -359,7 +359,8 @@ file_apprentice(struct magic_set *ms, co
                        *p++ = '\0';
                if (*fn == '\0')
                        break;
-               file_err = apprentice_1(ms, fn, action, mlist);
+               ms->file = fn;
+               file_err = apprentice_1(ms, action, mlist);
                errs = MAX(errs, file_err);
                fn = p;
        }
@@ -571,13 +572,15 @@ load_1(struct magic_set *ms, int action,
 {
        char line[BUFSIZ];
        size_t lineno = 0;
-       FILE *f = fopen(ms->file = fn, "r");
-       if (f == NULL) {
+       FILE *f;
+       
+       if ((f = fopen(fn, "r")) == NULL) {
                if (errno != ENOENT)
                        file_error(ms, errno, "cannot read magic file `%s'",
                                   fn);
                (*errs)++;
-       } else {
+               return;
+       } 
                /* read and parse this file */
                for (ms->line = 1; fgets(line, sizeof(line), f) != NULL; 
ms->line++) {
                        size_t len;
@@ -606,7 +609,6 @@ load_1(struct magic_set *ms, int action,
 
                (void)fclose(f);
        }
-}
 
 /*
  * parse a file or directory of files
@@ -614,7 +616,7 @@ load_1(struct magic_set *ms, int action,
  */
 private int
 apprentice_load(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
-    const char *fn, int action)
+    int action)
 {
        int errs = 0;
        struct magic_entry *marray;
@@ -625,7 +627,6 @@ apprentice_load(struct magic_set *ms, st
        struct dirent *d;
 
        ms->flags |= MAGIC_CHECK;       /* Enable checks for parsed files */
-
         maxmagic = MAXMAGIS;
        if ((marray = calloc(maxmagic, sizeof(*marray))) == NULL) {
                file_oomem(ms, maxmagic * sizeof(*marray));
@@ -638,12 +639,12 @@ apprentice_load(struct magic_set *ms, st
                (void)fprintf(stderr, "%s\n", usg_hdr);
 
        /* load directory or file */
-       if (stat(fn, &st) == 0 && S_ISDIR(st.st_mode)) {
-               dir = opendir(fn);
+       if (stat(ms->file, &st) == 0 && S_ISDIR(st.st_mode)) {
+               dir = opendir(ms->file);
                if (dir) {
                        while (d = readdir(dir)) {
                                snprintf(subfn, sizeof(subfn), "%s/%s",
-                                   fn, d->d_name);
+                                   ms->file, d->d_name);
                                if (stat(subfn, &st) == 0 && 
S_ISREG(st.st_mode)) {
                                        load_1(ms, action, subfn, &errs,
                                            &marray, &marraycount);
@@ -653,7 +654,7 @@ apprentice_load(struct magic_set *ms, st
                } else
                        errs++;
        } else
-               load_1(ms, action, fn, &errs, &marray, &marraycount);
+               load_1(ms, action, ms->file, &errs, &marray, &marraycount);
        if (errs)
                goto out;

Reply via email to