[PATCH v2 bpf-next 12/18] bpf: Follow integer casts in bpf_scan_ir
From: Anton Protopopov
Date: Mon Nov 09 2026 - 12:14:05 EST
Follow sign extensions and truncations between integers of at least 32
bits in the block of the return. They keep an error, for example an int
error which a function returns as long.
Signed-off-by: Anton Protopopov <a.s.protopopov@xxxxxxxxx>
---
scripts/llvm-plugins/bpf_scan_ir.cpp | 28 +++++++++++++++++++++++++---
1 file changed, 25 insertions(+), 3 deletions(-)
diff --git a/scripts/llvm-plugins/bpf_scan_ir.cpp b/scripts/llvm-plugins/bpf_scan_ir.cpp
index 81de8f941568..a3c6336662fc 100644
--- a/scripts/llvm-plugins/bpf_scan_ir.cpp
+++ b/scripts/llvm-plugins/bpf_scan_ir.cpp
@@ -82,17 +82,39 @@ static bool errnoConstant(const Value *V, int64_t &N)
return N >= -MaxErrno && N < 0;
}
+/* A sign extension or a truncation between integers of at least 32 bits */
+static bool preservesErrnoCast(const CastInst *Cast)
+{
+ Type *Src = Cast->getSrcTy(), *Dst = Cast->getDestTy();
+
+ if (Src->isIntegerTy() && Dst->isIntegerTy())
+ return (Cast->getOpcode() == Instruction::SExt ||
+ Cast->getOpcode() == Instruction::Trunc) &&
+ Src->getIntegerBitWidth() >= 32 && Dst->getIntegerBitWidth() >= 32;
+ return false;
+}
+
/*
* Add the errors which V, the value returned in RET, is known to be on the
- * edges to RET from CLEANBBS to VALUES. V may be a PHI in RET. A PHI in an
- * earlier block is not followed: a later branch may split its values between
- * clean and dirty paths.
+ * edges to RET from CLEANBBS to VALUES. Follow the casts in RET which keep the
+ * error to a PHI in RET. A PHI in an earlier block is not followed: a later
+ * branch may split its values between clean and dirty paths.
*/
static void collectErrnos(Value *V, BasicBlock *Ret, LazyValueInfo &LVI,
const SmallPtrSetImpl<BasicBlock *> &CleanBBs, ReturnValues &Values)
{
int64_t N;
+ while (auto *Cast = dyn_cast<CastInst>(V)) {
+ if (Cast->getParent() != Ret || !preservesErrnoCast(Cast))
+ return;
+ if (singleErrnoAtUse(Cast->getOperandUse(0), LVI, N)) {
+ Values.push_back(N);
+ return;
+ }
+ V = Cast->getOperand(0);
+ }
+
auto *Phi = dyn_cast<PHINode>(V);
if (!Phi || Phi->getParent() != Ret)
--
2.43.0