{"record":{"id":"17453d31fe858f73","repo":"NationalSecurityAgency/ghidra","slug":"s-error-too-many-files-encountered","errorCode":null,"errorMessage":"%s: error: too many @-files encountered","messagePattern":"(.+?): error: too many @-files encountered","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"GPL/DemanglerGnu/src/demangler_gnu_v2_24/c/argv.c","lineNumber":406,"sourceCode":"      /* The number of characters in the response file, when actually\n\t read.  */\n      size_t len;\n      /* A dynamically allocated buffer used to hold options read from a\n\t response file.  */\n      char *buffer;\n      /* Dynamically allocated storage for the options read from the\n\t response file.  */\n      char **file_argv;\n      /* The number of options read from the response file, if any.  */\n      size_t file_argc;\n      /* We are only interested in options of the form \"@file\".  */\n      filename = (*argvp)[i];\n      if (filename[0] != '@')\n\tcontinue;\n      /* If we have iterated too many times then stop.  */\n      if (-- iteration_limit == 0)\n\t{\n\t  fprintf (stderr, \"%s: error: too many @-files encountered\\n\", (*argvp)[0]);\n\t  xexit (1);\n\t}\n      /* Read the contents of the file.  */\n      f = fopen (++filename, \"r\");\n      if (!f)\n\tcontinue;\n      if (fseek (f, 0L, SEEK_END) == -1)\n\tgoto error;\n      pos = ftell (f);\n      if (pos == -1)\n\tgoto error;\n      if (fseek (f, 0L, SEEK_SET) == -1)\n\tgoto error;\n      buffer = (char *) xmalloc (pos * sizeof (char) + 1);\n      len = fread (buffer, sizeof (char), pos, f);\n      if (len != (size_t) pos\n\t  /* On Windows, fread may return a value smaller than POS,\n\t     due to CR/LF->CR translation when reading text files.","sourceCodeStart":388,"sourceCodeEnd":424,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/GPL/DemanglerGnu/src/demangler_gnu_v2_24/c/argv.c#L388-L424","documentation":"In libiberty's buildargv/expandargv-style argument processing (argv.c), command-line tokens of the form @file are expanded by reading the named response file and inserting its contents as arguments. A counter (iteration_limit, initialized to 2000) bounds how many @-files are processed to stop infinite recursion (e.g. @a includes @a, or a cycle). When the counter hits zero the program prints this error and calls xexit(1).","triggerScenarios":"Supplying a @file argument whose response file(s) transitively reference enough @-files to exhaust the 2000-deep limit, typically via a circular chain (file @a contains '@a') or a very deep, self-referential include graph.","commonSituations":"A generated response file accidentally includes itself (common with build tools that emit @file from a glob that contains the response file); a circular reference between two response files; an extremely large, deliberately nested set of @-files. This is a build/CLI invocation problem, not a runtime data problem.","solutions":["Check response files for self-references or mutual cycles (grep for the file's own name inside it).","Regenerate the response file so it lists only real arguments, never @-references back into itself.","Remove the @file indirection and pass arguments directly to confirm the cycle is the cause.","Audit build scripts/templates that produce @-files to exclude the response file path from its own contents."],"exampleFix":"# before: build/link.args contains a line '@link.args' (self-reference)\nclang @build/link.args main.c\n\n# after: regenerate build/link.args without self-inclusion\n# (e.g. exclude the args file itself from the glob that writes it)\nclang @build/link.args main.c","handlingStrategy":"validation","validationCode":"// Validate response files for self-reference before invoking the tool\n#include <stdio.h>\n#include <string.h>\nint self_references(const char *file) {\n    /* returns 1 if 'file' contains an @-ref to itself */\n    FILE *f = fopen(file, \"r\"); char line[4096]; int found = 0;\n    if (!f) return 0;\n    while (fgets(line, sizeof line, f))\n        if (strstr(line, file)) { found = 1; break; }\n    fclose(f); return found;\n}","typeGuard":"// detect a cycle in @-file references before passing to the tool\nbool hasResponseFileCycle(const std::vector<std::string>& files);","tryCatchPattern":"// This is a CLI invocation error that calls xexit(1); it cannot be caught.\n// Capture child stderr and non-zero exit code in the calling process:\nint rc = run_child({\"clang\", \"@build/args\", \"main.c\"});\nif (rc != 0 && stderr_contains(\"too many @-files\")) {\n    report(\"response file cycle detected; regenerating @build/args without self-reference\");\n}","preventionTips":["When generating @-files, exclude the response file's own path from its contents.","Lint response files for self-references and mutual cycles before builds.","Prefer passing arguments directly when the argument count is small.","Audit build scripts/templates that glob arguments into a file that the glob also matches."],"tags":["demangler","cli","response-files","recursion","build"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}