[llvm] [orc-rt] Add ORC_RT_LOG_PUB_S for logging runtime strings. (PR #209401)

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 14 01:37:35 PDT 2026


https://github.com/lhames created https://github.com/llvm/llvm-project/pull/209401

ORC_RT_LOG requires its format to be a string literal, so the specifier for a runtime C string cannot be written at the call site by hand -- and it differs by backend: os_log redacts a plain "%s" argument to <private> unless it carries a "%{public}s" annotation, which libc's printf does not understand.

Add ORC_RT_LOG_PUB_S, which expands to "%{public}s" on the os_log backend and plain "%s" everywhere else. Call sites compose it into the format by literal adjacency, so the format stays a single literal on every backend:

  ORC_RT_LOG(Info, General, "resolved " ORC_RT_LOG_PUB_S, SymbolName);

LoggingTest covers the compile/format-check path (including os_log builds); the orc-rt-log-check delivery test confirms os_log publishes the string rather than redacting it to <private>.

>From 5e475fd0fb909c67aa142c098b7deaa8ccba2b09 Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at gmail.com>
Date: Tue, 14 Jul 2026 18:23:37 +1000
Subject: [PATCH] [orc-rt] Add ORC_RT_LOG_PUB_S for logging runtime strings.

ORC_RT_LOG requires its format to be a string literal, so the specifier for a
runtime C string cannot be written at the call site by hand -- and it differs
by backend: os_log redacts a plain "%s" argument to <private> unless it carries
a "%{public}s" annotation, which libc's printf does not understand.

Add ORC_RT_LOG_PUB_S, which expands to "%{public}s" on the os_log backend and
plain "%s" everywhere else. Call sites compose it into the format by literal
adjacency, so the format stays a single literal on every backend:

  ORC_RT_LOG(Info, General, "resolved " ORC_RT_LOG_PUB_S, SymbolName);

LoggingTest covers the compile/format-check path (including os_log builds); the
orc-rt-log-check delivery test confirms os_log publishes the string rather than
redacting it to <private>.
---
 orc-rt/include/orc-rt-c/Logging.h             | 32 +++++++++++++++++++
 .../regression/logging/os_log/delivery.test   |  7 +++-
 orc-rt/test/tools/orc-rt-log-check.cpp        | 11 ++++++-
 orc-rt/test/unit/LoggingTest.cpp              |  5 +++
 4 files changed, 53 insertions(+), 2 deletions(-)

diff --git a/orc-rt/include/orc-rt-c/Logging.h b/orc-rt/include/orc-rt-c/Logging.h
index 60618d2f90a55..9f63e14a9a181 100644
--- a/orc-rt/include/orc-rt-c/Logging.h
+++ b/orc-rt/include/orc-rt-c/Logging.h
@@ -131,6 +131,38 @@ int orc_rt_log_formatCheck(const char *Fmt, ...) ORC_RT_C_FORMAT_PRINTF(1, 2);
   ((void)sizeof("" __VA_ARGS__, 0),                                            \
    ORC_RT_LOG_##Level(orc_rt_log_Category_##Category, __VA_ARGS__))
 
+/**
+ * \def ORC_RT_LOG_PUB_S
+ * Conversion specifier for publishing a runtime (non-literal) C string.
+ *
+ * Use this in place of a plain "%s" whenever you are logging a runtime string
+ * that should be readable in the log output: on os_log a "%s" argument defaults
+ * to private and is redacted in the system log, so ORC_RT_LOG_PUB_S is what
+ * actually publishes the bytes. Publishing is a privacy decision -- keep a
+ * plain "%s" (which stays private) for anything a sandboxed or privacy-
+ * sensitive deployment should not disclose, or do not log it at all. The printf
+ * backend has no public/private distinction and always prints the string
+ * regardless.
+ *
+ * ORC_RT_LOG requires Fmt to be a string literal, but the specifier for a
+ * runtime string differs by backend, so it cannot be written inline. This
+ * macro expands to a string literal that the surrounding format is expected to
+ * concatenate by literal adjacency, e.g.
+ *
+ *   ORC_RT_LOG(Info, General, "resolved " ORC_RT_LOG_PUB_S, SymbolName);
+ *
+ * keeping Fmt a single literal on every backend.
+ *
+ * ORC_RT_LOG_PUB_S expands to plain "%s" for backends other than os_log:
+ * neither libc's vprintf nor the printf-style format checkers understand
+ * os_log's "%{public}s" syntax.
+ */
+#if ORC_RT_LOG_BACKEND == ORC_RT_LOG_BACKEND_OS_LOG
+#define ORC_RT_LOG_PUB_S "%{public}s"
+#else
+#define ORC_RT_LOG_PUB_S "%s"
+#endif
+
 #if ORC_RT_LOG_BACKEND == ORC_RT_LOG_BACKEND_NONE
 
 /* The none backend compiles every level out, regardless of ORC_RT_LOG_LEVEL. */
diff --git a/orc-rt/test/regression/logging/os_log/delivery.test b/orc-rt/test/regression/logging/os_log/delivery.test
index 9432738fda8cc..32740cfceda50 100644
--- a/orc-rt/test/regression/logging/os_log/delivery.test
+++ b/orc-rt/test/regression/logging/os_log/delivery.test
@@ -7,6 +7,11 @@
 # the CHECK text, so the value reaches the pattern as [[uid]]). The record is
 # emitted at ERROR level, which os_log persists, so `log show` sees it;
 #
+# The record also carries a runtime string logged with ORC_RT_LOG_PUB_S. os_log
+# redacts a dynamic string to <private> unless it is published, so matching the
+# payload's contents (rather than <private>) confirms the public annotation
+# takes effect.
+#
 # REQUIRES: os-log-show-tests
 # RUN: orc-rt-log-check --uid %{orc-rt-log-uid}
 # RUN: log show --predicate \
@@ -14,4 +19,4 @@
 # RUN:     --style compact --last 15s \
 # RUN:     | FileCheck -Duid=%{orc-rt-log-uid} %s
 
-# CHECK: delivery marker uid=[[uid]]
+# CHECK: delivery marker uid=[[uid]] payload=public-payload
diff --git a/orc-rt/test/tools/orc-rt-log-check.cpp b/orc-rt/test/tools/orc-rt-log-check.cpp
index e38854f20665f..6e17091ac38a7 100644
--- a/orc-rt/test/tools/orc-rt-log-check.cpp
+++ b/orc-rt/test/tools/orc-rt-log-check.cpp
@@ -108,7 +108,16 @@ int main(int argc, char *argv[]) {
     // Emit one record whose payload carries the caller-supplied id, so a
     // delivery test can match exactly its own record and not a stale one. The
     // id is an integer (a %d scalar), which os_log shows unredacted.
-    ORC_RT_LOG(Error, General, "delivery marker uid=%d", UID);
+    //
+    // The record also carries a runtime string logged via ORC_RT_LOG_PUB_S. On
+    // the os_log backend a dynamic string argument is redacted to <private>
+    // unless the public annotation is applied, so a delivery test can confirm
+    // the annotation publishes the string by matching its contents rather than
+    // <private>.
+    const char *PublicPayload = "public-payload";
+    ORC_RT_LOG(Error, General,
+               "delivery marker uid=%d payload=" ORC_RT_LOG_PUB_S, UID,
+               PublicPayload);
     return 0;
   }
 
diff --git a/orc-rt/test/unit/LoggingTest.cpp b/orc-rt/test/unit/LoggingTest.cpp
index 186f5982bee00..6cd192f4deb81 100644
--- a/orc-rt/test/unit/LoggingTest.cpp
+++ b/orc-rt/test/unit/LoggingTest.cpp
@@ -26,6 +26,11 @@ TEST(LoggingTest, CompilesAtEveryLevel) {
   ORC_RT_LOG(Warning, General, "one arg: %d", 42);
   ORC_RT_LOG(Info, General, "two args: %s = %d", "answer", 42);
   ORC_RT_LOG(Debug, General, "wide arg: %llu", (unsigned long long)1 << 40);
+
+  // ORC_RT_LOG_PUB_S must concatenate into the literal format and type-check as
+  // a "%s" conversion against a runtime string on every backend.
+  const char *RuntimeStr = "runtime";
+  ORC_RT_LOG(Info, General, "public string: " ORC_RT_LOG_PUB_S, RuntimeStr);
   SUCCEED();
 }
 



More information about the llvm-commits mailing list