================ @@ -2074,16 +2091,91 @@ static bool checkPointerAuthValue(Sema &S, Expr *&Arg, if (convertArgumentToType(S, Arg, ExpectedTy)) return true; - // Warn about null pointers for non-generic sign and auth operations. - if ((OpKind == PAO_Sign || OpKind == PAO_Auth) && - Arg->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNull)) { - S.Diag(Arg->getExprLoc(), OpKind == PAO_Sign - ? diag::warn_ptrauth_sign_null_pointer - : diag::warn_ptrauth_auth_null_pointer) - << Arg->getSourceRange(); + if (!RequireConstant) { + // Warn about null pointers for non-generic sign and auth operations. + if ((OpKind == PAO_Sign || OpKind == PAO_Auth) && + Arg->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNull)) { + S.Diag(Arg->getExprLoc(), OpKind == PAO_Sign + ? diag::warn_ptrauth_sign_null_pointer + : diag::warn_ptrauth_auth_null_pointer) + << Arg->getSourceRange(); + } + + return false; } - return false; + // Perform special checking on the arguments to ptrauth_sign_constant. + + // The main argument. + if (OpKind == PAO_Sign) { + // Require the value we're signing to have a special form. + auto BaseOffsetPair = findConstantBaseAndOffset(S, Arg); + bool Invalid; + + // Must be rooted in a declaration reference. + if (!BaseOffsetPair.first) { + Invalid = true; + + // If it's a function declaration, we can't have an offset. + } else if (isa<FunctionDecl>(BaseOffsetPair.first)) { + Invalid = !BaseOffsetPair.second.isZero(); + + // Otherwise we're fine. + } else { + Invalid = false; + } + + if (Invalid) { + S.Diag(Arg->getExprLoc(), diag::err_ptrauth_bad_constant_pointer); + } + return Invalid; + } + + // The discriminator argument. + assert(OpKind == PAO_Discriminator); + + // Must be a pointer or integer or blend thereof. + Expr *Pointer = nullptr; + Expr *Integer = nullptr; + if (auto *Call = dyn_cast<CallExpr>(Arg->IgnoreParens())) { + if (Call->getBuiltinCallee() == + Builtin::BI__builtin_ptrauth_blend_discriminator) { + Pointer = Call->getArg(0); + Integer = Call->getArg(1); + } + } + if (!Pointer && !Integer) { + if (Arg->getType()->isPointerType()) + Pointer = Arg; + else + Integer = Arg; + } + + // Check the pointer. + bool Invalid = false; + if (Pointer) { + assert(Pointer->getType()->isPointerType()); + + // TODO: if we're initializing a global, check that the address is + // somehow related to what we're initializing. This probably will + // never really be feasible and we'll have to catch it at link-time. + auto BaseOffsetPair = findConstantBaseAndOffset(S, Pointer); + if (!BaseOffsetPair.first || !isa<VarDecl>(BaseOffsetPair.first)) { + Invalid = true; ---------------- ahmedbougacha wrote:
The missing base was covered, but the VarDecl check wasn't I think; I added tests where the discriminator is a function decl https://github.com/llvm/llvm-project/pull/93904 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits