{"record":{"id":"17c7c1724a082e8d","repo":"NationalSecurityAgency/ghidra","slug":"cannot-make-taint-concrete","errorCode":null,"errorMessage":"Cannot make taint concrete","messagePattern":"Cannot make taint concrete","errorType":"exception","errorClass":"ConcretionError","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/TaintAnalysis/src/main/java/ghidra/pcode/emu/taint/TaintPcodeArithmetic.java","lineNumber":233,"sourceCode":"\t * Constant values have no taint, so we just return a vector of empty taint sets\n\t */\n\t@Override\n\tpublic TaintVec fromConst(byte[] value) {\n\t\treturn TaintVec.empties(value.length);\n\t}\n\n\t/**\n\t * {@inheritDoc}\n\t * \n\t * <p>\n\t * Taint vectors have no values. We're expect the taint arithmetic to be used as an auxiliary to\n\t * concrete bytes, so the paired arithmetic should always defer to its concrete element. Thus,\n\t * an {@link AssertionError} might also be fitting here, but we'll stick to convention, since\n\t * technically a user script could attempt to concretize taint.\n\t */\n\t@Override\n\tpublic byte[] toConcrete(TaintVec value, Purpose purpose) {\n\t\tthrow new ConcretionError(\"Cannot make taint concrete\", purpose);\n\t}\n\n\t/**\n\t * {@inheritDoc}\n\t * \n\t * <p>\n\t * Taint vectors do have length, so return it here.\n\t */\n\t@Override\n\tpublic long sizeOf(TaintVec value) {\n\t\treturn value.length;\n\t}\n}\n","sourceCodeStart":215,"sourceCodeEnd":247,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/TaintAnalysis/src/main/java/ghidra/pcode/emu/taint/TaintPcodeArithmetic.java#L215-L247","documentation":"Taint is a label set, not a value - it has no bytes to concretize. toConcrete therefore throws ConcretionError. The arithmetic is designed to run as an auxiliary alongside a concrete arithmetic that owns the actual bytes, and the paired concrete arithmetic is what should answer concretization. ConcretionError is the framework's standard signal that this arithmetic cannot produce concrete bytes.","triggerScenarios":"The pcode executor or user code calls arithmetic.toConcrete(taintVec, purpose) - e.g. an instruction that needs a concrete constant (branch target, address computation), or a user script explicitly trying to read taint as bytes.","commonSituations":"Running a taint-only executor where an instruction forces concretization (conditional jumps, syscalls, address resolution); wiring taint as the primary arithmetic without a concrete partner; user scripts calling toConcrete on taint.","solutions":["Run taint as an auxiliary arithmetic paired with a concrete one, so the concrete arithmetic answers toConcrete.","Avoid ops that force concretization, or pre-supply concrete bytes for them.","Catch ConcretionError at a higher level if graceful degradation is acceptable for your analysis."],"exampleFix":"// before (taint used alone; toConcrete fails)\nbyte[] v = taintArithmetic.toConcrete(taintVec, Purpose.OTHER);\n// after (delegate concretization to the paired concrete arithmetic)\nbyte[] v = concreteArithmetic.toConcrete(concreteVec, Purpose.OTHER);","handlingStrategy":"fallback","validationCode":"// Route concretization to the paired concrete arithmetic:\nif (arithmetic instanceof TaintPcodeArithmetic) {\n    // do not call toConcrete on taint; use the concrete partner\n    return concreteArithmetic.toConcrete(concreteVec, purpose);\n}","typeGuard":null,"tryCatchPattern":"try {\n    return arithmetic.toConcrete(value, purpose);\n} catch (ConcretionError e) {\n    // fall back to the paired concrete arithmetic or skip the op\n}","preventionTips":["Always pair taint arithmetic with a concrete arithmetic that owns real bytes.","Avoid ops that force concretization in pure-taint analysis."],"tags":["pcode","emulation","taint","concretization"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}