I want to create a simple string encryption in C++ using the consteval keyword. Previously, I used constexpr, which worked, but some strings were encrypted at runtime. So, I decided to switch to consteval, which, as I understand, ensures that the function always runs at compile time.
Now I am getting this error:
Call to consteval function 'encrypt_string' is not a constant expression
pointer to subobject of temporary is not a constant expression
I am not sure what this mean.
Currently I am using a macro to encrypt the strings, and it is replaced with this code:
decrypt_string(encrypt_string((char[]) { "s/x/apkpath/MainActivity" }, sizeof(char[])
{ "s/x/apkpath/MainActivity" }),sizeof(char[])
{ "s/x/apkpath/MainActivity" })
encrypt_string()
is the function declared consteval.
the two functions look like this:
consteval auto encrypt_string(char string[], uint32_t len) {
for (int i = 0; i != len; i++) {
string[i] = string[i] ^ keys_expr[i & 7];
}
return string;
}
__attribute__((visibility("hidden"))) __attribute__((noinline)) __attribute__((optnone))
auto decrypt_string(char string[], int len) {
for (int i = 0; i != len; i++) {
string[i] = (string[i] & ~keys[i & 7]) | (~(string[i] & keys[i & 7]) & keys[i & 7]);
//string[i] = string[i] ^ keys[i & 7];
}
return string;
}
I am compiling this in Android Studio so the compiler should be clang. I added this line to build.gradle
externalNativeBuild {
cmake {
cppFlags '-std=c++20'
}
}
This is the full error:
C:\Users\*\AppData\Local\Android\Sdk\ndk\25.1.8937393\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=aarch64-none-linux-android24 --sysroot=C:/Users/*/AppData/Local/Android/Sdk/ndk/25.1.8937393/toolchains/llvm/prebuilt/windows-x86_64/sysroot -Dapkpath_EXPORTS -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -std=c++20 -fno-limit-debug-info -fPIC -MD -MT CMakeFiles/apkpath.dir/apkpath.cpp.o -MF CMakeFiles\apkpath.dir\apkpath.cpp.o.d -o CMakeFiles/apkpath.dir/apkpath.cpp.o -c C:/Users/*/AndroidStudioProjects/ApkPath/app/src/main/cpp/apkpath.cpp
C:/Users/*/AndroidStudioProjects/ApkPath/app/src/main/cpp/apkpath.cpp:15:17: error: call to consteval function 'encrypt_string' is not a constant expression
decrypt_string(encrypt_string((char[]) { "s/x/apkpath/MainActivity" }, sizeof(char[])
^
C:/Users/*/AndroidStudioProjects/ApkPath/app/src/main/cpp/apkpath.cpp:15:17: note: pointer to subobject of temporary is not a constant expression
C:/Users/*/AndroidStudioProjects/ApkPath/app/src/main/cpp/apkpath.cpp:15:32: note: temporary created here
decrypt_string(encrypt_string((char[]) { "s/x/apkpath/MainActivity" }, sizeof(char[])
^
That's not what
consteval
does.consteval
functions are not allowed to be invoked in places outside of constant evaluation (hence the name). It doesn't cause the invocation to be "compile-time"; it simply forbids uses outside of such evaluations.It's up to you to use your
consteval
function during constant evaluation. Your call todecrypt_string
is not constant evaluation, so callingencrypt_string
during that expression will be outside of constant evaluation. Hence the error.However, the fundamental algorithm you're trying to implement is not itself going to work. Your algorithm modifies the parameter, which is a string literal. String literals are explicitly
const
objects in C++, so modifying them is undefined behavior. And at compile-time, undefined behavior is ill-formed (aka: a compile error).If you want to make this work, your
consteval
function needs to return a new string, not modify the given pointer in-situ. This would generally be done via a template (to get the length of the string literal at compile time), returning a fixed-length string.