[llvm-branch-commits] [clang] [clang] Define ptrauth_sign_constant builtin. (PR #93904)

Ahmed Bougacha via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Jun 18 18:26:16 PDT 2024


================
@@ -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


More information about the llvm-branch-commits mailing list