r346211 - os_log: Allow specifying mask type in format string.
Akira Hatanaka via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 5 23:05:14 PST 2018
Author: ahatanak
Date: Mon Nov 5 23:05:14 2018
New Revision: 346211
URL: http://llvm.org/viewvc/llvm-project?rev=346211&view=rev
Log:
os_log: Allow specifying mask type in format string.
A mask type is a 1 to 8-byte string that follows the "mask." annotation
in the format string. This enables obfuscating data in the event the
provided privacy level isn't enabled.
rdar://problem/36756282
Modified:
cfe/trunk/include/clang/AST/FormatString.h
cfe/trunk/include/clang/AST/OSLog.h
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/AST/OSLog.cpp
cfe/trunk/lib/AST/PrintfFormatString.cpp
cfe/trunk/lib/CodeGen/CGBuiltin.cpp
cfe/trunk/lib/Sema/SemaChecking.cpp
cfe/trunk/test/CodeGen/builtins.c
cfe/trunk/test/SemaObjC/format-strings-oslog.m
Modified: cfe/trunk/include/clang/AST/FormatString.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/FormatString.h?rev=346211&r1=346210&r2=346211&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/FormatString.h (original)
+++ cfe/trunk/include/clang/AST/FormatString.h Mon Nov 5 23:05:14 2018
@@ -477,6 +477,7 @@ class PrintfSpecifier : public analyze_f
OptionalFlag IsPublic; // '{public}'
OptionalFlag IsSensitive; // '{sensitive}'
OptionalAmount Precision;
+ StringRef MaskType;
public:
PrintfSpecifier()
: FormatSpecifier(/* isPrintf = */ true), HasThousandsGrouping("'"),
@@ -559,6 +560,9 @@ public:
const OptionalFlag &isSensitive() const { return IsSensitive; }
bool usesPositionalArg() const { return UsesPositionalArg; }
+ StringRef getMaskType() const { return MaskType; }
+ void setMaskType(StringRef S) { MaskType = S; }
+
/// Changes the specifier and length according to a QualType, retaining any
/// flags or options. Returns true on success, or false when a conversion
/// was not successful.
@@ -691,6 +695,9 @@ public:
return true;
}
+ /// Handle mask types whose sizes are not between one and eight bytes.
+ virtual void handleInvalidMaskType(StringRef MaskType) {}
+
// Scanf-specific handlers.
virtual bool HandleInvalidScanfConversionSpecifier(
Modified: cfe/trunk/include/clang/AST/OSLog.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/OSLog.h?rev=346211&r1=346210&r2=346211&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/OSLog.h (original)
+++ cfe/trunk/include/clang/AST/OSLog.h Mon Nov 5 23:05:14 2018
@@ -52,7 +52,10 @@ public:
// The item is corresponding to the '%m' format specifier, no value is
// populated in the buffer and the runtime is loading the errno value.
- ErrnoKind
+ ErrnoKind,
+
+ // The item is a mask type.
+ MaskKind
};
enum {
@@ -72,10 +75,13 @@ private:
CharUnits ConstValue;
CharUnits Size; // size of the data, not including the header bytes
unsigned Flags = 0;
+ StringRef MaskType;
public:
- OSLogBufferItem(Kind kind, const Expr *expr, CharUnits size, unsigned flags)
- : TheKind(kind), TheExpr(expr), Size(size), Flags(flags) {
+ OSLogBufferItem(Kind kind, const Expr *expr, CharUnits size, unsigned flags,
+ StringRef maskType = StringRef())
+ : TheKind(kind), TheExpr(expr), Size(size), Flags(flags),
+ MaskType(maskType) {
assert(((Flags == 0) || (Flags == IsPrivate) || (Flags == IsPublic) ||
(Flags == IsSensitive)) &&
"unexpected privacy flag");
@@ -99,6 +105,8 @@ public:
const Expr *getExpr() const { return TheExpr; }
CharUnits getConstValue() const { return ConstValue; }
CharUnits size() const { return Size; }
+
+ StringRef getMaskType() const { return MaskType; }
};
class OSLogBufferLayout {
@@ -122,9 +130,10 @@ public:
Items, [](const OSLogBufferItem &Item) { return Item.getIsPrivate(); });
}
- bool hasNonScalar() const {
+ bool hasNonScalarOrMask() const {
return llvm::any_of(Items, [](const OSLogBufferItem &Item) {
- return Item.getKind() != OSLogBufferItem::ScalarKind;
+ return Item.getKind() != OSLogBufferItem::ScalarKind ||
+ !Item.getMaskType().empty();
});
}
@@ -132,7 +141,7 @@ public:
unsigned char result = 0;
if (hasPrivateItems())
result |= HasPrivateItems;
- if (hasNonScalar())
+ if (hasNonScalarOrMask())
result |= HasNonScalarItems;
return result;
}
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=346211&r1=346210&r2=346211&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Nov 5 23:05:14 2018
@@ -7902,6 +7902,8 @@ def warn_format_non_standard: Warning<
def warn_format_non_standard_conversion_spec: Warning<
"using length modifier '%0' with conversion specifier '%1' is not supported by ISO C">,
InGroup<FormatNonStandard>, DefaultIgnore;
+def err_invalid_mask_type_size : Error<
+ "mask type size must be between 1-byte and 8-bytes">;
def warn_format_invalid_annotation : Warning<
"using '%0' format specifier annotation outside of os_log()/os_trace()">,
InGroup<Format>;
Modified: cfe/trunk/lib/AST/OSLog.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/OSLog.cpp?rev=346211&r1=346210&r2=346211&view=diff
==============================================================================
--- cfe/trunk/lib/AST/OSLog.cpp (original)
+++ cfe/trunk/lib/AST/OSLog.cpp Mon Nov 5 23:05:14 2018
@@ -26,6 +26,7 @@ private:
Optional<const Expr *> Precision;
Optional<const Expr *> FieldWidth;
unsigned char Flags = 0;
+ StringRef MaskType;
};
SmallVector<ArgData, 4> ArgsData;
ArrayRef<const Expr *> Args;
@@ -127,12 +128,19 @@ public:
else if (FS.isPublic())
ArgsData.back().Flags |= OSLogBufferItem::IsPublic;
+ ArgsData.back().MaskType = FS.getMaskType();
return true;
}
void computeLayout(ASTContext &Ctx, OSLogBufferLayout &Layout) const {
Layout.Items.clear();
for (auto &Data : ArgsData) {
+ if (!Data.MaskType.empty()) {
+ CharUnits Size = CharUnits::fromQuantity(8);
+ Layout.Items.emplace_back(OSLogBufferItem::MaskKind, nullptr,
+ Size, 0, Data.MaskType);
+ }
+
if (Data.FieldWidth) {
CharUnits Size = Ctx.getTypeSizeInChars((*Data.FieldWidth)->getType());
Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, *Data.FieldWidth,
Modified: cfe/trunk/lib/AST/PrintfFormatString.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/PrintfFormatString.cpp?rev=346211&r1=346210&r2=346211&view=diff
==============================================================================
--- cfe/trunk/lib/AST/PrintfFormatString.cpp (original)
+++ cfe/trunk/lib/AST/PrintfFormatString.cpp Mon Nov 5 23:05:14 2018
@@ -127,7 +127,8 @@ static PrintfSpecifierResult ParsePrintf
do {
StringRef Str(I, E - I);
- std::string Match = "^[[:space:]]*(private|public|sensitive)"
+ std::string Match = "^[[:space:]]*"
+ "(private|public|sensitive|mask\\.[^[:space:],}]*)"
"[[:space:]]*(,|})";
llvm::Regex R(Match);
SmallVector<StringRef, 2> Matches;
@@ -139,7 +140,13 @@ static PrintfSpecifierResult ParsePrintf
// Set the privacy flag if the privacy annotation in the
// comma-delimited segment is at least as strict as the privacy
// annotations in previous comma-delimited segments.
- if (MatchedStr.equals("sensitive"))
+ if (MatchedStr.startswith("mask")) {
+ StringRef MaskType = MatchedStr.substr(sizeof("mask.") - 1);
+ unsigned Size = MaskType.size();
+ if (Warn && (Size == 0 || Size > 8))
+ H.handleInvalidMaskType(MaskType);
+ FS.setMaskType(MaskType);
+ } else if (MatchedStr.equals("sensitive"))
PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsSensitive;
else if (PrivacyFlags !=
clang::analyze_os_log::OSLogBufferItem::IsSensitive &&
Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=346211&r1=346210&r2=346211&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Mon Nov 5 23:05:14 2018
@@ -1168,7 +1168,12 @@ RValue CodeGenFunction::emitBuiltinOSLog
llvm::Value *ArgVal;
- if (const Expr *TheExpr = Item.getExpr()) {
+ if (Item.getKind() == analyze_os_log::OSLogBufferItem::MaskKind) {
+ uint64_t Val = 0;
+ for (unsigned I = 0, E = Item.getMaskType().size(); I < E; ++I)
+ Val |= ((unsigned )Item.getMaskType()[I]) << I * 8;
+ ArgVal = llvm::Constant::getIntegerValue(Int64Ty, llvm::APInt(64, Val));
+ } else if (const Expr *TheExpr = Item.getExpr()) {
ArgVal = EmitScalarExpr(TheExpr, /*Ignore*/ false);
// Check if this is a retainable type.
Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=346211&r1=346210&r2=346211&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Mon Nov 5 23:05:14 2018
@@ -7135,6 +7135,8 @@ public:
const char *startSpecifier,
unsigned specifierLen) override;
+ void handleInvalidMaskType(StringRef MaskType) override;
+
bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
const char *startSpecifier,
unsigned specifierLen) override;
@@ -7186,6 +7188,10 @@ bool CheckPrintfHandler::HandleInvalidPr
CS.getStart(), CS.getLength());
}
+void CheckPrintfHandler::handleInvalidMaskType(StringRef MaskType) {
+ S.Diag(getLocationOfByte(MaskType.data()), diag::err_invalid_mask_type_size);
+}
+
bool CheckPrintfHandler::HandleAmount(
const analyze_format_string::OptionalAmount &Amt,
unsigned k, const char *startSpecifier,
Modified: cfe/trunk/test/CodeGen/builtins.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/builtins.c?rev=346211&r1=346210&r2=346211&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/builtins.c (original)
+++ cfe/trunk/test/CodeGen/builtins.c Mon Nov 5 23:05:14 2018
@@ -454,6 +454,22 @@ void test_builtin_os_log(void *buf, int
// CHECK: call void @__os_log_helper_1_3_1_8_37(
__builtin_os_log_format(buf, "%{ private, sensitive, private, public}s",
"abc");
+
+ // CHECK: store volatile i32 22, i32* %[[LEN]], align 4
+ len = __builtin_os_log_format_buffer_size("%{mask.xyz}s", "abc");
+
+ // CHECK: call void @__os_log_helper_1_2_2_8_112_8_34(i8* {{.*}}, i64 8026488
+ __builtin_os_log_format(buf, "%{mask.xyz, public}s", "abc");
+
+ // CHECK: call void @__os_log_helper_1_3_2_8_112_4_1(i8* {{.*}}, i64 8026488
+ __builtin_os_log_format(buf, "%{ mask.xyz, private }d", 11);
+
+ // Mask type is silently ignored.
+ // CHECK: call void @__os_log_helper_1_2_1_8_32(
+ __builtin_os_log_format(buf, "%{ mask. xyz }s", "abc");
+
+ // CHECK: call void @__os_log_helper_1_2_1_8_32(
+ __builtin_os_log_format(buf, "%{ mask.xy z }s", "abc");
}
// CHECK-LABEL: define linkonce_odr hidden void @__os_log_helper_1_3_4_4_0_8_34_4_17_8_49
Modified: cfe/trunk/test/SemaObjC/format-strings-oslog.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/format-strings-oslog.m?rev=346211&r1=346210&r2=346211&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/format-strings-oslog.m (original)
+++ cfe/trunk/test/SemaObjC/format-strings-oslog.m Mon Nov 5 23:05:14 2018
@@ -39,6 +39,10 @@ void test_os_log_format(const char *pc,
struct { char data[0x100]; } toobig;
__builtin_os_log_format(buf, "%s", toobig); // expected-error {{os_log() argument 2 is too big (256 bytes, max 255)}}
+
+ __builtin_os_log_format(buf, "%{mask.xyz}s", "abc");
+ __builtin_os_log_format(buf, "%{mask.}s", "abc"); // expected-error {{mask type size must be between 1-byte and 8-bytes}}
+ __builtin_os_log_format(buf, "%{mask.abcdefghi}s", "abc"); // expected-error {{mask type size must be between 1-byte and 8-bytes}}
}
// Test os_log_format primitive with ObjC string literal format argument.
More information about the cfe-commits
mailing list