Home > Enterprise >  Is the LLVM compiler smart enough to remove code within a non-reachable if statement?
Is the LLVM compiler smart enough to remove code within a non-reachable if statement?

Time:11-16

The following assumes a Swift environment using the LLVM compiler.

GIVEN I have the following:

var isDebug: Bool {
    #if DEBUG
    return true
    #else
    return false
    #endif
}

WHEN the environment flag DEBUG is NOT set
AND the following code is compiled

var secret = ""
if isDebug {
    secret = "abc123" 
}
print(secret)

THEN

  1. Will the compiled binary contain the string "abc123" somewhere within it or will the compiler remove it?

  2. Is this just as "safe" as using:

var secret = ""
#if DEBUG
    secret = "abc123" 
#endif
print(secret)

CodePudding user response:

Based on how you structured it, yes, the compiled code will have your secret, and no, it's not as safe as using conditional compilation block. Reason is that isDebug is present regardless of the state of conditional compilation block, and hence code inside if will be compiled (it won't be used of course if DEBUG, but it will be present).

So you really have to stick to using a conditional compilation block directly, i.e. as in your second example:

var secret = ""
#if DEBUG
    secret = "abc123" 
#endif

But also looking at your use case (i.e. secrets), the problem here is not just that compiled code may or may not contain your secret, it's also a bad idea to store secrets in the code - whether you are using github, or internal source control.

Instead, you can inject your secret at build time, retrieving it from the safe store. There are many options, one of the simplest ones is putting a secret into PLIST, and storing it securely away from source code, and retrieving it at compilation time if it's needed. Here is a good tutorial on this and some other options

CodePudding user response:

It might be removed when compiled with -O, but there is no promise of this behavior. You can demonstrate that for this trivial code, it does work:

% swift --version
swift-driver version: 1.26.9 Apple Swift version 5.5.1 (swiftlang-1300.0.31.4 clang-1300.0.29.6)
Target: arm64-apple-macosx12.0

% cat x.swift
var isDebug: Bool {
    #if DEBUG
    return true
    #else
    return false
    #endif
}

var secret = ""
if isDebug {
    secret = "abc123"
}
print(secret)

% swiftc x.swift && strings x | grep abc123
abc123

% swiftc -O x.swift && strings x | grep abc123
%

But this code is particularly simple and easy for the optimizer. There is no promise that arbitrary code will optimize this way, and there's no promise that future versions of the compiler will optimize this way.

  • Related