malloc (): поврежденный верхний размер - PullRequest
0 голосов
/ 27 мая 2019

Я работаю над программой, которая расшифровывает некоторую строку текста в файле. Во-первых, другой исходный код, который я создал, требует сдвига и некоторого текста. Исходный код шифрует текст и записывает его в файл.

Затем я пытаюсь расшифровать указанный файл, используя приведенный ниже код - другой исходный код. Название файла получено. Из имени файла получается сдвиг. Каждый символ, записанный в файле, копируется, сдвигается на значение shift с помощью функции caesar_decrypt -reversing caesar encrypt, которую я также имею. Однако указанные символы должны иметь значение ascii между 32 и 127, чтобы их можно было преобразовать в другой символ значения ascii между 32 и 127.

Я определил свою функцию по модулю, заключающую в себе оператор остатка - модуль положительных чисел - и модуль отрицательных чисел. Я также определил функцию полосы, которая работает так же, как функция полосы в питоне. Помимо пробелов, он удаляет все литералы. У меня также есть getIn (), который является input () Python.

Я попытался отладить, печатая и используя gdb. Нет эффективного результата. Я исследовал эту тему в stackoverflow. Нашел одну запись. Ответ не касается моей конкретной проблемы.

ПРИМЕЧАНИЕ: я скопировал всю программу, так как думал, что вам понадобится необходимая подробная информация.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <unistd.h>
#include <fcntl.h>

/*GETIN FUNCTION*/
char* getIn() 
{
    char *line = NULL, *tmp = NULL;
    size_t size = 0, index = 0;
    int ch = EOF;

    while (ch) 
    {
        ch = getc(stdin);

        /* Check if we need to stop. */
        if (ch == EOF || ch == '\n')
        ch = 0;

        /* Check if we need to expand. */
        if (size <= index) 
        {
            size += sizeof(char);
            tmp = realloc(line, size);
            if (!tmp) 
            {
                free(line);
                line = NULL;
                break;
            }
        line = tmp;
        }

    /* Actually store the thing. */
    line[index++] = ch;
    }

    return line;
}
/*FUNCTION THAT CONVERTS TO NUMERIC CHARACTER, PRECURSOR OF DIGITS OF SHIFT*/
char make_numeric(char ch)
{
    if(ch<91 && ch>63) return ch-16;
    if(ch<123 && ch>95) return ch-48;
    if(ch<58 && ch>47) return ch;
    return ch+16;
}

 /*STRIP FUNCTION*/
char* strip(char* str,int length)
{
    char *start=str,*end=&str[length-1];

    while(*start>0 && *start<33 || *start==127) ++start;
    if(!*start) return start;

    while(*end>=0 && *end<33 || *end==127) --end;
    ++end;
    *end=0;

    return start;
}
/*DECRYPTOR FUNCTION*/
char *caesar_decrypt(char *message_to_decrypt, void *shift)
{   
    int length=strlen(message_to_decrypt),i;
    char* decrypted_message;

    if(!message_to_decrypt) return NULL;

    if(!(decrypted_message=calloc(length+1,sizeof(char)))) return NULL;

    for(i=0;i<length;++i)
    {
    decrypted_message[i]=mod((message_to_decrypt[i]-33-*((int*)shift)),94)+33;
    }

return decrypted_message;
}   

/*THE MAIN PROGRAM*/
int main()
{

int shift,len_chshift,init,len_filename,i=0;
char *chshift,*line=NULL,*decrypted_line,*stripped_line,chinit,chlen_chshift;
char *filename=NULL,*newfilename=NULL;
FILE *oldfile=NULL;
FILE *newfile=NULL;
size_t lenline,len=0;

printf("-9");
/*FILENAME*/
printf("Enter the file name: ");
/*printf("-8");*/
filename=getIn();
/*printf("-7");*/
if(!access(filename,F_OK))
{
    len_filename=strlen(filename);
    /*printf("-6");*/
    i=len_filename;
    while(filename[i]!='.') --i;        
    chlen_chshift=filename[i-1];
    chlen_chshift=make_numeric(chlen_chshift);
    len_chshift=chlen_chshift-48;
    /*printf("-5");*/
    chshift=calloc(len_chshift+1,1);
    /*NEWFILENAME*/
    newfilename=calloc(i+1,1);
    /*printf("-4");*/
    strncpy(newfilename,filename,i);
    /*printf("-3");*/
    strcat(newfilename,"(decrypted).txt");
    /*printf("-2");*/
    chinit=make_numeric(filename[0]);
    init=chinit-48;
    /*SHIFT*/
    i=0;
    /*printf("-1");*/
    while(i!=len_chshift)
    {
        chshift[i]=make_numeric(filename[(i+1)*init]);
        ++i;
    }
    /*printf("0");*/
    shift=atoi(chshift);

    /*printf("1");*/
    if(!(oldfile=fopen(filename,"r")))
    {
        perror("Error");
        if(newfilename) free(newfilename);
        if(filename) free(filename);
        if(chshift) free(chshift);
        exit(1);
    }
    /*printf("2");*/

    if(!(newfile=fopen(newfilename,"+ab")))
    {
        perror("Error");
        if(newfilename) free(newfilename);
        if(filename) free(filename);
        if(chshift) free(chshift);
        fclose(oldfile);
        exit(1);
    }
    while ((lenline = getline(&line, &len, oldfile)) != -1)
    {
        stripped_line=strip(line,lenline);
        decrypted_line=caesar_decrypt(stripped_line, &shift);
        if(!decrypted_line)
        {
            printf("Could not allocate memory\n");
            if(newfilename) free(newfilename);
            if(filename) free(filename);
            if(chshift) free(chshift);
            exit(1);
        }

        fprintf(newfile,"%s\n",decrypted_line);

        if(decrypted_line) free(decrypted_line);
        decrypted_line=NULL;

        free(line);
        line=NULL;
        stripped_line=NULL;
        decrypted_line=NULL;
    }
    free(line);
    line=NULL;
}
else
{
    printf("Cannot access the file.");
    if(filename) free(filename);
    exit(0);
}

if(newfilename) free(newfilename);
if(filename) free(filename);
if(chshift) free(chshift);

fclose(oldfile);
fclose(newfile);
return 0;
}

Программа требуется для создания файла, контекстом которого является расшифрованный клон другого файла, имя которого вначале предоставляется пользователем. Тем не менее, он бросает, как раз перед первым fopen:

malloc(): corrupted top size
Aborted (core dumped)

Когда я раскомментирую каждую строку printf, она выдает одинаковую ошибку между строками getIn () и printf ("- 7") ;. Когда закомментированы printfs, я вижу, что имя файла содержит записанное значение, которое возвращается getIn (). Поэтому я не думаю, что getIn () является проблемой.

РЕДАКТИРОВАТЬ (1) : я добавил 2 заголовка, которые отсутствовали, но все равно вызывали ту же ошибку.

EDIT (2) : я удалил все ненужные заголовки.

РЕДАКТИРОВАТЬ (3) : Поскольку меня просят, я попытаюсь осветить на примере: Предположим, у меня есть файл с именем

2/b*A".txt

с двумя строками кода

%52
abcd

Я ввожу имя файла в программу.

1) Самый последний символ перед . - это ", преобразованный в число 2 . Мы понимаем, что shift - это двузначное число.

2) Первым символом является инициатор, а 2 - это количество символов, которое мы должны повторно прыгнуть. Мы прыгнем на два символа дважды, так как у нас есть сдвиг из двух цифр.

3) Теперь мы изменили символы b и A на 2 и 1 соответственно. Наш сдвиг - 21. Самый первый символ % (37) смещается назад к n (110) и так далее, нам нужно создать новый файл с содержимым:

n~#
LMNO

Я ценю любую помощь. Заранее спасибо. Кроме того, переменные, которые я упомянул, являются произвольными символами между определенными интервалами. За подробностями обращайтесь к исходному коду или я предлагаю вам работать локально, так как я предоставил всю программу.

Для кодов ascii: https://www.asciitable.com/

Если вас интересует шифр Цезаря: https://en.wikipedia.org/wiki/Caesar_cipher

1 Ответ

2 голосов
/ 27 мая 2019

У вас переполнение буфера в newfilename:

/* here you declare that the string pointed to by newfilename may contain `i`
   chars + zero-termination...*/ 
newfilename=calloc(i+1,1);

/* Here `i` is less than `strlen(filename)`, so only i characters from `filename`
   will be copied, that does NOT include the zero-termination
   (but it will be zero-terminated because the last byte in the buffer was 
   already cleared by `calloc`) */ 
strncpy(newfilename,filename,i);


/* Here `newfilename` is full, and `strcat` will write outside buffer!! Whatever
   happens after this line is undefined behaviour */   
strcat(newfilename,"(decrypted).txt");

Таким образом, вы должны выделить достаточно места для newfilename:

newfilename = calloc (i + strlen("(decrypted).txt") + 1, 1);
...