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;
}

enter image description here

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[])
                                      ^
1

There are 1 answers

16
Nicol Bolas On

which, as I understand, ensures that the function always runs at compile time

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 to decrypt_string is not constant evaluation, so calling encrypt_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.