{"record":{"id":"a7438d69c2b8af65","repo":"NationalSecurityAgency/ghidra","slug":"string-must-not-begin-or-end-with-a-comma","errorCode":null,"errorMessage":"String must not begin or end with a comma","messagePattern":"String must not begin or end with a comma","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"warning","filePath":"Ghidra/Extensions/MachineLearning/src/main/java/ghidra/machinelearning/functionfinding/FunctionStartRFParams.java","lineNumber":220,"sourceCode":"\t\t\tcontextRegisterNames.add(regName);\n\t\t\tBigInteger bigInt = new BigInteger(regValPair[1].trim());\n\t\t\tcontextRegisterVals.add(bigInt);\n\t\t}\n\t}\n\n\t/**\n\t * Parses a CSV into a sorted list of distinct integer values (duplicates are ignored).  Returns\n\t * an empty list of a parse error is encountered.\n\t * @param csv csv string to parse\n\t * @return sorted list  \n\t */\n\tpublic static List<Integer> parseIntegerCSV(String csv) {\n\t\tif (StringUtils.isBlank(csv)) {\n\t\t\tthrow new IllegalArgumentException(\"Entry cannot be blank\");\n\t\t}\n\t\tString trimmed = csv.trim();\n\t\tif (trimmed.startsWith(\",\") || trimmed.endsWith(\",\")) {\n\t\t\tthrow new IllegalArgumentException(\"String must not begin or end with a comma\");\n\t\t}\n\t\tSet<Integer> results = new HashSet<>();\n\t\tString[] parts = trimmed.split(\",\");\n\t\tfor (String part : parts) {\n\t\t\tInteger i = Integer.decode(part.trim());\n\t\t\tif (i < 0) {\n\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"Invalid element \" + part + \" - must be non-negative\");\n\t\t\t}\n\t\t\tresults.add(i);\n\t\t}\n\t\treturn results.stream().sorted().collect(Collectors.toList());\n\t}\n\n\t/**\n\t * Returns the {@link AddressSet} of function entries in the source program.\n\t * <P>\n\t * NB: Invoke {@link FunctionStartRFParams#computeFuncEntriesAndInteriors} before","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Extensions/MachineLearning/src/main/java/ghidra/machinelearning/functionfinding/FunctionStartRFParams.java#L202-L238","documentation":"Thrown by parseIntegerCSV(csv) after trimming, when the string starts or ends with a comma (e.g. ',1,2' or '1,2,'). split(\",\") on such input would yield an empty leading/trailing element and a confusing NumberFormatException later, so this is caught early with a clear message.","triggerScenarios":"parseIntegerCSV(\",1,2,3\"); parseIntegerCSV(\"1,2,\"); a CSV built by joining a list that included an empty/null tail element.","commonSituations":"Trailing comma from manual entry or from String.join on a list containing an empty string; copy-paste artifacts; UI text field with a stray comma at the cursor.","solutions":["Remove leading/trailing commas before submitting: csv.replaceAll(\"^[,\\\\s]+|[,\\\\s]+$\", \"\").","Build the CSV from non-empty tokens only (filter blanks before joining).","Validate in the UI that the field does not begin or end with ','."],"exampleFix":"// before\nparseIntegerCSV(\"1,2,\"); // trailing comma -> throws\n\n// after\nparseIntegerCSV(\"1,2\");","handlingStrategy":"validation","validationCode":"String safe = csv == null ? \"\" : csv.trim().replaceAll(\"^[,\\\\s]+|[,\\\\s]+$\", \"\");\nif (!safe.isEmpty()) {\n    List<Integer> r = FunctionStartRFParams.parseIntegerCSV(safe);\n}","typeGuard":"null","tryCatchPattern":"try {\n    List<Integer> r = FunctionStartRFParams.parseIntegerCSV(csv);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"begin or end with a comma\")) {\n        List<Integer> r = FunctionStartRFParams.parseIntegerCSV(csv.trim().replaceAll(\"^[,]+|[,]+$\", \"\"));\n    } else throw e;\n}","preventionTips":["Strip leading/trailing commas and whitespace before parsing.","Build CSV with String.join(\",\", tokens) over a filtered (non-empty) list.","Validate field boundaries in the UI on loss of focus."],"tags":["machine-learning","validation","config-parsing","function-finder"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}