Há um tempo atrás eu havia postado no Shorts, Reels e Tik Tok um código que criava uma forma simples e rápida de codificar e decodificar strings que pode ser usado para inúmeras situações onde as pessoas só esperam codificadores como: base64, por exemplo.
Logo, essa maneira, dificulta um pouco mais saber qual o algoritmo para decodificar. O código C++ se resumia ao conteúdo abaixo:
#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;
}
Apesar de funcionar, esse código possui alguns problemas:
constexpr
, estamos modificando o ponteiro da string, tornar a função do tipo void
é o mais lógico;encode
não faz verificação de final de linha e isso resulta em um problema grave que causa corrupção de memória.Eu percebi isso quando fui implementar em uma solução que estava criando, onde eu só copiei o código gerado pela função encode
e fui usar em um aplicativo e quando tentei rodar apareceu a seguinte falha:
*** stack smashing detected ***: terminated
Abortado (imagem do núcleo gravada)
Logo, o código corrigido fica assim:
#include <iostream>
#include <string>
void encode(char * s) {
while (*s != '\0') { // Verifica o fim da string
++(*s); // Incrementa o caractere atual
++s; // Avança para o próximo caractere
}
}
void decode(char * s) {
while (*s != '\0') { // Verifica o fim da string
--(*s); // Decrementa o caractere atual
++s; // Avança para o próximo caractere
}
}
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;
}
Agora se você copiar o resultado codificado poderá usá-lo para decodificar em outra implementação sem chance de ter um stack smashing.
Para confirmar isso você pode usar flags que verificam se houve violação de memória, exemplo:
g++ -g -Wpedantic -Wall -Werror -fsanitize=address encode.cpp
Após rodar, exemplo:
./a.out "Terminal Root"
Encode: Ufsnjobm!Sppu
Decode: Terminal Root
Se quiser dificultar ainda mais, você pode usar loops
para rodar a função quantas vezes você quiser e usar o mesmo número de vezes para decodificar, exemplo do que estou falando sem loops:
Isso, modifica 4 vezes a string e usamos 4 vezes novamente para retonar a 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';
Ou usando o um 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';
Em ambos os casos a saída será a mesma:
./a.out "Terminal Root"
Encode: Xivqmrep$Vssx
Decode: Terminal Root
Como funciona?
encode
. Por exemplo:
Para mais informações sugiro os links: