[clang] c8048c7 - [attributes] Generalize attribute 'enforce_tcb' to Objective-C methods.
Artem Dergachev via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 28 15:08:58 PDT 2022
Author: Pierre d'Herbemont
Date: 2022-03-28T15:08:47-07:00
New Revision: c8048c7c42ffd1731149b0abe15b9081dd27c789
URL: https://github.com/llvm/llvm-project/commit/c8048c7c42ffd1731149b0abe15b9081dd27c789
DIFF: https://github.com/llvm/llvm-project/commit/c8048c7c42ffd1731149b0abe15b9081dd27c789.diff
LOG: [attributes] Generalize attribute 'enforce_tcb' to Objective-C methods.
Calling an ObjC method from a C function marked with the 'enforce_tcb'
attribute did not produce a warning. Now it does, and on top of that
Objective-C methods can participate in TCBs themselves.
Differential Revision: https://reviews.llvm.org/D122343
Added:
clang/test/Sema/attr-enforce-tcb-errors.m
clang/test/Sema/attr-enforce-tcb.m
Modified:
clang/include/clang/Basic/Attr.td
clang/include/clang/Sema/Sema.h
clang/lib/Sema/SemaChecking.cpp
clang/test/Misc/pragma-attribute-supported-attributes-list.test
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index a35b2fcbc4fb5..f7ef3bf42ec2f 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -3915,7 +3915,7 @@ def Builtin : InheritableAttr {
def EnforceTCB : InheritableAttr {
let Spellings = [Clang<"enforce_tcb">];
- let Subjects = SubjectList<[Function]>;
+ let Subjects = SubjectList<[Function, ObjCMethod]>;
let Args = [StringArgument<"TCBName">];
let Documentation = [EnforceTCBDocs];
bit InheritEvenIfAlreadyPresent = 1;
@@ -3923,7 +3923,7 @@ def EnforceTCB : InheritableAttr {
def EnforceTCBLeaf : InheritableAttr {
let Spellings = [Clang<"enforce_tcb_leaf">];
- let Subjects = SubjectList<[Function]>;
+ let Subjects = SubjectList<[Function, ObjCMethod]>;
let Args = [StringArgument<"TCBName">];
let Documentation = [EnforceTCBLeafDocs];
bit InheritEvenIfAlreadyPresent = 1;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 53ac1d011d9e1..379e120e3a117 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -12988,7 +12988,8 @@ class Sema final {
/// attempts to add itself into the container
void CheckObjCCircularContainer(ObjCMessageExpr *Message);
- void CheckTCBEnforcement(const CallExpr *TheCall, const FunctionDecl *Callee);
+ void CheckTCBEnforcement(const SourceLocation CallExprLoc,
+ const NamedDecl *Callee);
void AnalyzeDeleteExprMismatch(const CXXDeleteExpr *DE);
void AnalyzeDeleteExprMismatch(FieldDecl *Field, SourceLocation DeleteLoc,
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index e02104b4699e1..14e82e54eacb3 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -5497,7 +5497,9 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
if (!FnInfo)
return false;
- CheckTCBEnforcement(TheCall, FDecl);
+ // Enforce TCB except for builtin calls, which are always allowed.
+ if (FDecl->getBuiltinID() == 0)
+ CheckTCBEnforcement(TheCall->getExprLoc(), FDecl);
CheckAbsoluteValueFunction(TheCall, FDecl);
CheckMaxUnsignedZero(TheCall, FDecl);
@@ -5537,6 +5539,8 @@ bool Sema::CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation lbrac,
/*IsMemberFunction=*/false, lbrac, Method->getSourceRange(),
CallType);
+ CheckTCBEnforcement(lbrac, Method);
+
return false;
}
@@ -17359,13 +17363,11 @@ ExprResult Sema::SemaBuiltinMatrixColumnMajorStore(CallExpr *TheCall,
/// CheckTCBEnforcement - Enforces that every function in a named TCB only
/// directly calls other functions in the same TCB as marked by the enforce_tcb
/// and enforce_tcb_leaf attributes.
-void Sema::CheckTCBEnforcement(const CallExpr *TheCall,
- const FunctionDecl *Callee) {
- const FunctionDecl *Caller = getCurFunctionDecl();
+void Sema::CheckTCBEnforcement(const SourceLocation CallExprLoc,
+ const NamedDecl *Callee) {
+ const NamedDecl *Caller = getCurFunctionOrMethodDecl();
- // Calls to builtins are not enforced.
- if (!Caller || !Caller->hasAttr<EnforceTCBAttr>() ||
- Callee->getBuiltinID() != 0)
+ if (!Caller || !Caller->hasAttr<EnforceTCBAttr>())
return;
// Search through the enforce_tcb and enforce_tcb_leaf attributes to find
@@ -17383,9 +17385,8 @@ void Sema::CheckTCBEnforcement(const CallExpr *TheCall,
[&](const auto *A) {
StringRef CallerTCB = A->getTCBName();
if (CalleeTCBs.count(CallerTCB) == 0) {
- this->Diag(TheCall->getExprLoc(),
- diag::warn_tcb_enforcement_violation) << Callee
- << CallerTCB;
+ this->Diag(CallExprLoc, diag::warn_tcb_enforcement_violation)
+ << Callee << CallerTCB;
}
});
}
diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
index 944090509f55e..daae71f5167c4 100644
--- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -61,8 +61,8 @@
// CHECK-NEXT: DisableSanitizerInstrumentation (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_variable_is_global)
// CHECK-NEXT: DisableTailCalls (SubjectMatchRule_function, SubjectMatchRule_objc_method)
// CHECK-NEXT: EnableIf (SubjectMatchRule_function)
-// CHECK-NEXT: EnforceTCB (SubjectMatchRule_function)
-// CHECK-NEXT: EnforceTCBLeaf (SubjectMatchRule_function)
+// CHECK-NEXT: EnforceTCB (SubjectMatchRule_function, SubjectMatchRule_objc_method)
+// CHECK-NEXT: EnforceTCBLeaf (SubjectMatchRule_function, SubjectMatchRule_objc_method)
// CHECK-NEXT: EnumExtensibility (SubjectMatchRule_enum)
// CHECK-NEXT: Error (SubjectMatchRule_function)
// CHECK-NEXT: ExcludeFromExplicitInstantiation (SubjectMatchRule_variable, SubjectMatchRule_function, SubjectMatchRule_record)
diff --git a/clang/test/Sema/attr-enforce-tcb-errors.m b/clang/test/Sema/attr-enforce-tcb-errors.m
new file mode 100644
index 0000000000000..f82d38c919d1d
--- /dev/null
+++ b/clang/test/Sema/attr-enforce-tcb-errors.m
@@ -0,0 +1,100 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+int foo();
+
+__attribute__((objc_root_class))
+ at interface AClass
+- (void)bothTCBAndTCBLeafOnSeparateRedeclarations __attribute__((enforce_tcb("x"))); // expected-note{{conflicting attribute is here}}
+
+- (void)bothTCBAndTCBLeafOnSeparateRedeclarationsOppositeOrder __attribute__((enforce_tcb_leaf("x"))); // expected-note{{conflicting attribute is here}}
+
+- (void)bothTCBAndTCBLeafButDifferentIdentifiersOnSeparateRedeclarations __attribute__((enforce_tcb("x")));
+
+- (void)bothTCBAndTCBLeafButDifferentIdentifiersOnSeparateRedeclarationsOppositeOrder __attribute__((enforce_tcb_leaf("x")));
+
+- (void)onInterfaceOnly __attribute__((enforce_tcb("test")));
+ at end
+
+ at interface AClass (NoImplementation)
+- (void)noArguments __attribute__((enforce_tcb)); // expected-error{{'enforce_tcb' attribute takes one argument}}
+
+- (void)tooManyArguments __attribute__((enforce_tcb("test", 12))); // expected-error{{'enforce_tcb' attribute takes one argument}}
+
+- (void)wrongArgumentType __attribute__((enforce_tcb(12))); // expected-error{{'enforce_tcb' attribute requires a string}}
+
+- (void)noArgumentsLeaf __attribute__((enforce_tcb_leaf)); // expected-error{{'enforce_tcb_leaf' attribute takes one argument}}
+
+- (void)tooManyArgumentsLeaf __attribute__((enforce_tcb_leaf("test", 12))); // expected-error{{'enforce_tcb_leaf' attribute takes one argument}}
+
+- (void)wrongArgumentTypeLeaf __attribute__((enforce_tcb_leaf(12))); // expected-error{{'enforce_tcb_leaf' attribute requires a string}}
+ at end
+
+ at implementation AClass
+- (void)onInterfaceOnly {
+ foo(); // expected-warning{{calling 'foo' is a violation of trusted computing base 'test'}}
+}
+
+- (void)bothTCBAndTCBLeaf
+ __attribute__((enforce_tcb("x")))
+ __attribute__((enforce_tcb_leaf("x"))) // expected-error{{attributes 'enforce_tcb_leaf("x")' and 'enforce_tcb("x")' are mutually exclusive}}
+{
+ foo(); // no-warning
+}
+
+- (void)bothTCBAndTCBLeafOnSeparateRedeclarations
+ __attribute__((enforce_tcb_leaf("x"))) // expected-error{{attributes 'enforce_tcb_leaf("x")' and 'enforce_tcb("x")' are mutually exclusive}}
+{
+ // Error recovery: no need to emit a warning when we didn't
+ // figure out our attributes to begin with.
+ foo(); // no-warning
+}
+
+- (void)bothTCBAndTCBLeafOppositeOrder
+ __attribute__((enforce_tcb_leaf("x")))
+ __attribute__((enforce_tcb("x"))) // expected-error{{attributes 'enforce_tcb("x")' and 'enforce_tcb_leaf("x")' are mutually exclusive}}
+{
+ foo(); // no-warning
+}
+
+- (void)bothTCBAndTCBLeafOnSeparateRedeclarationsOppositeOrder
+ __attribute__((enforce_tcb("x"))) // expected-error{{attributes 'enforce_tcb("x")' and 'enforce_tcb_leaf("x")' are mutually exclusive}}
+{
+ foo(); // no-warning
+}
+
+- (void)bothTCBAndTCBLeafButDifferentIdentifiers
+ __attribute__((enforce_tcb("x")))
+ __attribute__((enforce_tcb_leaf("y"))) // no-error
+{
+ foo(); // expected-warning{{calling 'foo' is a violation of trusted computing base 'x'}}
+}
+
+- (void)bothTCBAndTCBLeafButDifferentIdentifiersOppositeOrder
+ __attribute__((enforce_tcb_leaf("x")))
+ __attribute__((enforce_tcb("y"))) // no-error
+{
+ foo(); // expected-warning{{calling 'foo' is a violation of trusted computing base 'y'}}
+}
+
+- (void)bothTCBAndTCBLeafButDifferentIdentifiersOnSeparateRedeclarations
+ __attribute__((enforce_tcb_leaf("y"))) // no-error
+{
+ foo(); // expected-warning{{calling 'foo' is a violation of trusted computing base 'x'}}
+}
+
+- (void)bothTCBAndTCBLeafButDifferentIdentifiersOnSeparateRedeclarationsOppositeOrder
+ __attribute__((enforce_tcb("y"))) {
+ foo(); // expected-warning{{calling 'foo' is a violation of trusted computing base 'y'}}
+}
+
+- (void)errorRecoveryOverIndividualTCBs
+ __attribute__((enforce_tcb("y")))
+ __attribute__((enforce_tcb("x")))
+ __attribute__((enforce_tcb_leaf("x"))) // expected-error{{attributes 'enforce_tcb_leaf("x")' and 'enforce_tcb("x")' are mutually exclusive}}
+{
+ // FIXME: Ideally this should warn. The conflict between attributes
+ // for TCB "x" shouldn't affect the warning about TCB "y".
+ foo(); // no-warning
+}
+
+ at end
diff --git a/clang/test/Sema/attr-enforce-tcb.m b/clang/test/Sema/attr-enforce-tcb.m
new file mode 100644
index 0000000000000..40b92c4293ec7
--- /dev/null
+++ b/clang/test/Sema/attr-enforce-tcb.m
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+#define PLACE_IN_TCB(NAME) __attribute__((enforce_tcb(NAME)))
+#define PLACE_IN_TCB_LEAF(NAME) __attribute__((enforce_tcb_leaf(NAME)))
+
+__attribute__((objc_root_class))
+ at interface AClass
+ at property(readonly) id propertyNotInAnyTCB;
+ at end
+
+ at implementation AClass
+- (void)inTCBFoo PLACE_IN_TCB("foo") {
+ [self notInAnyTCB]; // expected-warning{{calling 'notInAnyTCB' is a violation of trusted computing base 'foo'}}
+}
+- (void)inTCBFooAsLeaf PLACE_IN_TCB_LEAF("foo") {
+ [self notInAnyTCB]; // no-warning
+}
+- (void)notInAnyTCB {
+}
++ (void)classMethodNotInAnyTCB {
+}
++ (void)classMethodInTCBFoo PLACE_IN_TCB("foo") {
+ [self inTCBFoo]; // no-warning
+ [self inTCBFooAsLeaf]; // no-warning
+ [self notInAnyTCB]; // expected-warning{{calling 'notInAnyTCB' is a violation of trusted computing base 'foo'}}
+}
+ at end
+
+PLACE_IN_TCB("foo")
+void call_objc_method(AClass *object) {
+ [object inTCBFoo]; // no-warning
+ [object inTCBFooAsLeaf]; // no-warning
+ [object notInAnyTCB]; // expected-warning{{calling 'notInAnyTCB' is a violation of trusted computing base 'foo'}}
+ [AClass classMethodNotInAnyTCB]; // expected-warning{{calling 'classMethodNotInAnyTCB' is a violation of trusted computing base 'foo'}}
+ [AClass classMethodInTCBFoo]; // no-warning
+ (void)object.propertyNotInAnyTCB; // expected-warning{{calling 'propertyNotInAnyTCB' is a violation of trusted computing base 'foo'}}
+}
More information about the cfe-commits
mailing list