NationalSecurityAgency/ghidra · critical

%s: error: @-file refers to a directory\n

Error message

%s: error: @-file refers to a directory\n

What it means

When expanding an @file argument, expandargv calls stat() on the path. If S_ISDIR reports the path is a directory, the tool cannot read it as a text response file and calls xexit(1). The check is guarded by #ifdef S_ISDIR.

Source

Thrown at GPL/DemanglerGnu/src/demangler_gnu_v2_41/c/argv.c:414

#ifdef S_ISDIR
      struct stat sb;
#endif
      /* We are only interested in options of the form "@file".  */
      filename = (*argvp)[i];
      if (filename[0] != '@')
	continue;
      /* If we have iterated too many times then stop.  */
      if (-- iteration_limit == 0)
	{
	  fprintf (stderr, "%s: error: too many @-files encountered\n", (*argvp)[0]);
	  xexit (1);
	}
#ifdef S_ISDIR
      if (stat (filename+1, &sb) < 0)
	continue;
      if (S_ISDIR(sb.st_mode))
	{
	  fprintf (stderr, "%s: error: @-file refers to a directory\n", (*argvp)[0]);
	  xexit (1);
	}
#endif
      /* Read the contents of the file.  */
      f = fopen (++filename, "r");
      if (!f)
	continue;
      if (fseek (f, 0L, SEEK_END) == -1)
	goto error;
      pos = ftell (f);
      if (pos == -1)
	goto error;
      if (fseek (f, 0L, SEEK_SET) == -1)
	goto error;
      buffer = (char *) xmalloc (pos * sizeof (char) + 1);
      len = fread (buffer, sizeof (char), pos, f);
      if (len != (size_t) pos
	  /* On Windows, fread may return a value smaller than POS,

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Point the @file argument at an actual file, not a directory
  2. Verify the path exists and is a regular file with `ls -la`
  3. Fix the build script that generates the @file path

Example fix

# before
./tool @mydir
# after
./tool @mydir/options.txt
Defensive patterns

Strategy: validation

Validate before calling

// Validate @file arguments: ensure they point to regular files, not directories
#include <sys/stat.h>
static int validate_at_files(int argc, char *const argv[]) {
    for (int i = 0; i < argc; i++) {
        if (argv[i][0] != '@') continue;
        struct stat sb;
        if (stat(argv[i] + 1, &sb) == 0 && S_ISDIR(sb.st_mode)) {
            fprintf(stderr, "@-file '%s' is a directory\n", argv[i] + 1);
            return 0;
        }
    }
    return 1;
}

Type guard

static int is_regular_at_file(const char *arg) {
    if (!arg || arg[0] != '@') return 0;
    struct stat sb;
    if (stat(arg + 1, &sb) != 0) return 0;
    return S_ISREG(sb.st_mode);
}

Prevention

When it happens

Trigger: User passes `@/some/path` where that path resolves to a directory (S_ISDIR is true). The stat succeeds but the mode check fails. The tool exits with code 1.

Common situations: Typo or wrong path in the @file argument pointing to a directory; build system generates the @file path incorrectly; accidentally using a directory path instead of a file path.

Related errors


AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14). Data as JSON: /api/errors/0172930aa6b514f1. Report an issue: GitHub.