Эта подпрограмма принимает три пользовательских ввода: текстовую строку, путь к файлу и флаг из 1 цифры. Он загружает файл в буфер, а затем добавляет и флаг, и файловый буфер в указанном порядке к массиву символов, который служит полезной нагрузкой. Он возвращает полезную нагрузку и исходную строку пользователя.
Я получил ошибку, из-за которой некоторые из моих строковых операций с файловым буфером, флагом и полезной нагрузкой, по-видимому, повреждали память, в которой находилась user_string. Я исправил ошибку, заменив strcat(flag, buffer)
на strcpy(payload, flag)
(это то, что я изначально намеревался написать ), но я все еще недоумеваю, что вызвало эту ошибку.
Мое предположение, прочитанное в документации (https://www.gnu.org/software/libc/manual/html_node/Concatenating-Strings.html , https://www.gnu.org/software/libc/manual/html_node/Concatenating-Strings.html) состоит в том, что strcat
расширяет to
строку strlen(to)
байт в незащищенную память, содержимое которой загружается в буфер, копируется при переполнении буфера.
Мои вопросы:
Верна ли моя догадка?
Есть ли способ надежно предотвратить это? Отлов такого рода вещей с помощью проверки
if(){}
ненадежен, поскольку он не всегда возвращает что-то явно неправильное; вы ожидаете строку длинойfilelength+1
и получаете строкуfilelength+1
.бонус/не связанный: есть ли какие-либо вычислительные затраты/недостатки/эффекты при вызове переменной без работы с ней?
/*
user inputs:
argv[0] = tendigitaa/four
argv[1] = ~/Desktop/helloworld.txt
argv[2] = 1
helloworld.txt is a text file containing (no quotes) : "Hello World"
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
int main (int argc, char **argv) {
char user_string[100] = "0";
char file_path[100] = "0";
char flag[1] = "0";
strcpy(user_string, argv[1]);
strcpy(file_path, argv[2]);
strcpy(flag, argv[3]);
/*
at this point printfs of the three declared variables return the same as the user inputs.
======
======
a bunch of other stuff happens...
======
======
and then this point printfs of the three declared variables return the same as the user inputs.
*/
FILE *file;
char * buffer = 0;
long filelength;
file = fopen(file_path, "r");
if (file) {
fseek(file, 0, SEEK_END);
filelength = ftell(file);
fseek(file, 0, SEEK_SET);
buffer = malloc(filelength);
printf("stringcheck1: %s \n", user_string);
if (buffer) {
fread(buffer, 1, filelength, file);
}
}
long payloadlen = filelength + 1;
char payload[payloadlen];
printf("stringcheck2: %s \n", user_string);
strcpy(payload, flag);
printf("stringcheck3: %s \n", user_string);
strcat(flag, buffer);
printf("stringcheck4: %s \n", user_string); //bug here
free(buffer);
printf("stringcheck5: %s \n", user_string);
payload; user_string; //bonus question: does this line have any effect on the program or computational cost?
return 0;
}
/*
printf output:
stringcheck1: tendigitaa/four
stringcheck2: tendigitaa/four
stringcheck3: tendigitaa/four
stringcheck4: lo World
stringcheck5: lo World
*/
примечание: удаление этого раздела из основной программы привело к segfault stringcheck
4 вместо возврата "lo World". В остальном поведение было эквивалентным.