A while ago I posted on Shorts, Reels and Tik Tok a code that created a simple and fast way to encode and decode strings that can be used for countless situations where people only expect encoders like: base64, for example.
Therefore, this method makes it a little more difficult to know which algorithm to use to decode. The C++ code was summarized as follows:
#include <iostream>
constexpr auto encode = [](auto S){
while((*S++)++);
};
constexpr auto decode = [](auto S){
while(--(*S++));
};
int main(int argc, char **argv){
std::string str {};
if(argc > 1){
str = argv[1];
}else{ return EXIT_FAILURE;}
encode(str.data());
std::cout << "Encode: " << str << '\n';
decode(str.data());
std::cout << "Decode: " << str << '\n';
return EXIT_SUCCESS;
}
Although it works, this code has some problems:
constexpr
, we are modifying the pointer of the string, making the function of type void
is the most logical;encode
function does not check for end of line and this results in a serious problem that causes memory corruption.I realized this when I was implementing it in a solution I was creating, where I just copied the code generated by the encode
function and used it in an application and when I tried to run it, the following error appeared:
*** stack smashing detected ***: terminated
Aborted (core image saved)
Therefore, the corrected code looks like this:
#include <iostream>
void encode(char * s) {
while (*s != '\0') { // Check the end of the string
++(*s); // Increment the current character
++s; // Advance to the next character
}
}
void decode(char * s) {
while (*s != '\0') { // Check the end of the string
--(*s); // Decrement the current character
++s; // Advance to the next character
}
}
int main(int argc, char **argv) {
if (argc > 1) {
std::string str = argv[1];
encode(str.data());
std::cout << "Encode: " << str << '\n';
decode(str.data());
std::cout << "Decode: " << str << '\n';
}
return EXIT_SUCCESS;
}
Now if you copy the encoded result you can use it to decode in another implementation without having a stack smashing.
To confirm this, you can use flags that check if there was a memory violation, for example:
g++ -g -Wpedantic -Wall -Werror -fsanitize=address encode.cpp
After running, for example:
./a.out "Terminal Root"
Encode: Ufsnjobm!Sppu
Decode: Terminal Root
If you want to make it even more difficult, you can use loops
to run the function as many times as you want and use the same number of times to decode, for example, what I’m talking about without loops:
That’s it, modifies the string 4 times and we use it 4 times again to return the string original:
encode(str.data());
encode(str.data());
encode(str.data());
encode(str.data());
std::cout << "Encode: " << str << '\n';
decode(str.data());
decode(str.data());
decode(str.data());
decode(str.data());
std::cout << "Decode: " << str << '\n';
Or using a loop for
:
for(int i = {}; i < 4; ++i){
encode(str.data());
}
std::cout << "Encode: " << str << '\n';
for(int i = {}; i < 4; ++i){
decode(str.data());
}
std::cout << "Decode: " << str << '\n';
In both cases the output will be the same:
./a.out "Terminal Root"
Encode: Xivqmrep$Vssx
Decode: Terminal Root
How does it work?
encode
operation. For example:For more information, I suggest the following links: