|
9 | 9 | #ifndef LLVM_SUPPORT_IOSANDBOX_H |
10 | 10 | #define LLVM_SUPPORT_IOSANDBOX_H |
11 | 11 |
|
| 12 | +// Always enable IO sandboxing in debug/assert builds for development, |
| 13 | +// but allow enablement even for release/no-assert builds for production. |
| 14 | +#if !defined(NDEBUG) || defined(LLVM_ENABLE_IO_SANDBOX) |
| 15 | + |
| 16 | +#include "llvm/Support/ErrorHandling.h" |
12 | 17 | #include "llvm/Support/SaveAndRestore.h" |
13 | 18 |
|
14 | | -namespace llvm::sys { |
15 | | -SaveAndRestore<bool> sandbox_scoped_enable(); |
16 | | -SaveAndRestore<bool> sandbox_scoped_disable(); |
17 | | -void sandbox_violation_if_enabled(); |
18 | | -} // namespace llvm::sys |
| 19 | +namespace llvm::sys::sandbox { |
| 20 | +inline thread_local bool Enabled = false; |
| 21 | +inline SaveAndRestore<bool> scopedEnable() { return {Enabled, true}; } |
| 22 | +inline SaveAndRestore<bool> scopedDisable() { return {Enabled, false}; } |
| 23 | +inline void violationIfEnabled() { |
| 24 | + if (Enabled) |
| 25 | + reportFatalInternalError("IO sandbox violation"); |
| 26 | +} |
| 27 | +} // namespace llvm::sys::sandbox |
| 28 | + |
| 29 | +#else |
| 30 | + |
| 31 | +namespace llvm::sys::sandbox { |
| 32 | +inline int scopedEnable() {} |
| 33 | +inline int scopedDisable() {} |
| 34 | +inline void violationIfEnabled() {} |
| 35 | +} // namespace llvm::sys::sandbox |
| 36 | + |
| 37 | +#endif |
| 38 | + |
| 39 | +namespace llvm::sys::sandbox { |
| 40 | +/// Facility for seamlessly interposing function calls and sandbox enforcement. |
| 41 | +/// This is intended for creating static functors like so: |
| 42 | +/// |
| 43 | +/// // before |
| 44 | +/// #include <unistd.h> |
| 45 | +/// namespace x { |
| 46 | +/// void perform_read() { read(); } // not sandboxed |
| 47 | +/// } |
| 48 | +/// |
| 49 | +/// // after |
| 50 | +/// #include <unistd.h> |
| 51 | +/// namespace x { |
| 52 | +/// static constexpr auto read = llvm::sys::sandbox::interpose(::read); |
| 53 | +/// void perform_read() { read(); } // sandboxed |
| 54 | +/// } |
| 55 | +template <class FnTy> struct Interposed; |
| 56 | + |
| 57 | +template <class RetTy, class... ArgTy> struct Interposed<RetTy (*)(ArgTy...)> { |
| 58 | + RetTy (*Fn)(ArgTy...); |
| 59 | + |
| 60 | + RetTy operator()(ArgTy... Arg) const { |
| 61 | + violationIfEnabled(); |
| 62 | + return Fn(std::forward<ArgTy>(Arg)...); |
| 63 | + } |
| 64 | +}; |
| 65 | + |
| 66 | +template <class RetTy, class... ArgTy> |
| 67 | +struct Interposed<RetTy (*)(ArgTy..., ...)> { |
| 68 | + RetTy (*Fn)(ArgTy..., ...); |
| 69 | + |
| 70 | + template <class... CVarArgTy> |
| 71 | + RetTy operator()(ArgTy... Arg, CVarArgTy... CVarArg) const { |
| 72 | + violationIfEnabled(); |
| 73 | + return Fn(std::forward<ArgTy>(Arg)..., std::forward<CVarArgTy>(CVarArg)...); |
| 74 | + } |
| 75 | +}; |
| 76 | + |
| 77 | +template <class FnTy> constexpr auto interpose(FnTy Fn) { |
| 78 | + return Interposed<FnTy>{Fn}; |
| 79 | +} |
| 80 | +} // namespace llvm::sys::sandbox |
19 | 81 |
|
20 | 82 | #endif |
0 commit comments