{"record":{"id":"fb4a78ecd9649538","repo":"NationalSecurityAgency/ghidra","slug":"all-function-symbols-are-not-from-the-same-program-fb4a78","errorCode":null,"errorMessage":"all function symbols are not from the same program","messagePattern":"all function symbols are not from the same program","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/facade/SFQueryInfo.java","lineNumber":69,"sourceCode":"\t * @throws IllegalArgumentException if {@code functions} is {@code null}/empty or functions\n\t * are from multiple programs.  \n\t */\n\tpublic SFQueryInfo(Set<FunctionSymbol> functions) {\n\t\tif (functions == null) {\n\t\t\tthrow new IllegalArgumentException(\"Function list cannot be null\");\n\t\t}\n\n\t\tif (functions.isEmpty()) {\n\t\t\tthrow new IllegalArgumentException(\"Function list cannot be empty\");\n\t\t}\n\n\t\tthis.functions = functions;\n\t\tfor (FunctionSymbol s : functions) {\n\t\t\tif (program == null) {\n\t\t\t\tprogram = s.getProgram();\n\t\t\t}\n\t\t\telse if (program != s.getProgram()) {\n\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"all function symbols are not from the same program\");\n\t\t\t}\n\t\t}\n\t\tqueryNearest = new QueryNearest();\n\t\tbsimFilter = new BSimFilter();\n\t\tpreFilter = new PreFilter();\n\t}\n\n\t/**\n\t * @return the program from which all queried functions are from\n\t */\n\tpublic Program getProgram() {\n\t\treturn program;\n\t}\n\n\t/**\n\t * Gets the threshold under which a potential similar function will not be matched.  This\n\t * threshold is for how similar the potential function is. This is a value from 0.0 to 1.0. The ","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/facade/SFQueryInfo.java#L51-L87","documentation":"Thrown by the SFQueryInfo constructor when the function set contains symbols from more than one Program. The constructor locks in the first symbol's program and rejects any symbol whose getProgram() differs, because a single QueryNearest must run against one signature/address context. Third ordered check.","triggerScenarios":"Passing a set assembled across multiple open programs, or mixing main-program symbols with external/library symbols that report a different Program.","commonSituations":"Cross-program selection; a script that aggregates symbols from several Program objects into one set; selection spanning a program and its imported library.","solutions":["Partition the set by getProgram() and issue one SFQueryInfo per program.","Scope selection gathering to the current/active program.","Drop external/library symbols (different Program) from the set before construction."],"exampleFix":"// before\nSet<FunctionSymbol> mixed = gatherAcrossPrograms();\nSFQueryInfo info = new SFQueryInfo(mixed);\n// after\nMap<Program, List<Set<FunctionSymbol>>> grouped = mixed.stream()\n    .collect(Collectors.groupingBy(FunctionSymbol::getProgram));\ngrouped.values().forEach(syms -> {\n    SFQueryInfo info = new SFQueryInfo(new HashSet<>(syms));\n});","handlingStrategy":"validation","validationCode":"Map<Program, Set<FunctionSymbol>> byProgram = functions.stream()\n    .collect(Collectors.groupingBy(FunctionSymbol::getProgram, Collectors.toSet()));\nfor (Set<FunctionSymbol> per : byProgram.values()) {\n    SFQueryInfo info = new SFQueryInfo(per);\n}","typeGuard":"static boolean singleProgram(Set<FunctionSymbol> fns) {\n    return fns.stream().map(FunctionSymbol::getProgram).distinct().count() <= 1;\n}","tryCatchPattern":"try {\n    new SFQueryInfo(functions);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"same program\")) { /* split per program */ }\n}","preventionTips":["Gather selection from the active program only.","Partition mixed sets before constructing SFQueryInfo.","Exclude external/library symbols from a different Program."],"tags":["bsim","facade","validation","multi-program","query"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}