Декодирование шифра Виженера не работает должным образом

Я пишу шифр Виженера, который будет использоваться как часть загружаемого модуля ядра. Таким образом, я не могу использовать библиотеку строк. Вот почему я включил отдельные циклы для получения длины ключа и ввода. Оператор include и main включены только для тестирования.

Всякий раз, когда я использую ключ, который не состоит из всех заглавных букв, программа аварийно завершает работу из-за ошибки дезинфицирующего средства адреса. Это происходит только тогда, когда я включаю код, который должен преобразовывать ввод с клавиатуры в верхний регистр. Я не уверен, где это неверно, поскольку мой метод преобразования в верхний регистр такой же, как я видел в прошлом при переполнении стека. Он будет работать нормально и не вылетит без этих строк.

Кроме того, фаза декодирования не работает должным образом, она выдает неверное декодированное сообщение. Единственная возможная проблема, которую я могу представить, заключается в том, что я разрешаю вводу содержать пробелы, но я не думаю, что это проблема, поскольку я просто добавляю пробел в строку. Я был бы очень признателен за некоторую информацию о том, где я ошибаюсь в этом коде. Полная ошибка при попытке преобразования в верхний регистр:

==25694==ERROR: AddressSanitizer: BUS on unknown address 0x00010c98ae80 (pc 0x00010c989ac2 bp 0x7ffee3277610 sp 0x7ffee3277440 T0)
    #0 0x10c989ac1 in encrypt (vig:x86_64+0x100001ac1)
    #1 0x10c98aca1 in main (vig:x86_64+0x100002ca1)
    #2 0x7fff5c419ef8 in start (libdyld.dylib:x86_64+0x16ef8)

==25694==Register values:
rax = 0x000000010c98ae80  rbx = 0x00007ffee3277440  rcx = 0x000000010c98ae4b  rdx = 0x0000000000000004  
rdi = 0x000000010c98ae80  rsi = 0x000000010c98ae4b  rbp = 0x00007ffee3277610  rsp = 0x00007ffee3277440  
 r8 = 0x00001000219315d0   r9 = 0x0000000000000004  r10 = 0x0000000000000000  r11 = 0x0000000000000000  
r12 = 0x0000000000000000  r13 = 0x0000000000000000  r14 = 0x0000000000000000  r15 = 0x0000000000000000  
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: BUS (vig:x86_64+0x100001ac1) in encrypt
==25694==ABORTING
Abort trap: 6

Вот мой код:

#include<stdio.h>
#include<stdlib.h>
char* encrypt(char* input, char* key)
{
    int keyLength = 0;
    int inputLength = 0;
    int i;
    int j;
    for(i = 0; key[i] != '\0'; i++) //Get the length of the key
    {
        keyLength++;
    }
    for(i = 0; input[i] != '\0'; i++) //Get the length of the input
    {
        inputLength++;
    }
    for (i = 0; i < keyLength; i++)
    {
        if(key[i] >= 'a' && key[i] <= 'z')
        {
             key[i] = key[i] - 'a' + 'A';
        }
    }

    char* encryptedMessage = (char *)malloc((inputLength+1)*sizeof(char)); //Malloc for the encrypted message
    char fixedKey[inputLength + 1];
    if(inputLength < keyLength)
    {
        for(i =0; i < inputLength; i++)
        {
            fixedKey[i] = key[i];
        }
    }
    for(i = 0, j = 0; i < inputLength; ++i, ++j) //If the key length is shorter than message length, loop the key to correct length
    {
        printf("Entered Loop\n");
        if(j == keyLength)
            j = 0;
        fixedKey[i] = key[j];
    }
    fixedKey[i] = '\0';
    for(i = 0; i < inputLength; ++i) //Encryption
    {
        if(input[i] == ' ')
        {
            encryptedMessage[i] = ' ';
            continue;
        }
        encryptedMessage[i] = ((input[i] + fixedKey[i]) % 26) + 'A';
    }
    encryptedMessage[i] = '\0';
    return encryptedMessage;
}
char* decrypt(char* input, char* key)
{
    int keyLength = 0;
    int inputLength = 0;
    int i;
    int j;
    for(i = 0; key[i] != '\0'; i++) //Get the length of the key
    {
        keyLength++;
    }
    for(i = 0; input[i] != '\0'; i++) //Get the length of the input
    {
        inputLength++;
    }
    for (i = 0; i <keyLength; i++)
    {
        if(key[i] >= 'a' && key[i] <= 'z')
        {
            key[i] = key[i] - 'a' + 'A';
        }
    }
    char* decryptedMessage = (char *)malloc((inputLength+1)*sizeof(char));
    char fixedKey[inputLength + 1];
    if(inputLength < keyLength)
    {
        for(i =0; i < inputLength; i++)
        {
            fixedKey[i] = key[i];
        }
    }
    for(i = 0, j = 0; i < inputLength; ++i, ++j) //Fix the key length if needed
    {
        if(j == keyLength)
            j = 0;
        fixedKey[i] = key[j];
    }
    fixedKey[i] = '\0';
    for(i = 0; i < inputLength; ++i) //Decryption
    {
        if(input[i] == ' ')
        {
            decryptedMessage[i] = ' ';
            continue;
        }
        decryptedMessage[i] = (((input[i] - fixedKey[i]) + 26) % 26) + 'A';
    }
    decryptedMessage[i] = '\0';
    return decryptedMessage;
}
int main()
{
    char* encrypted = encrypt("The quick brown fox jumps over lazy dogs","key");
    char* decrypted = decrypt(encrypted,"key");
    printf("Encrypted string is: %s\nDecrypted String is: %s\n",encrypted,decrypted);
    return 0;
}

person Colin Null    schedule 08.11.2018    source источник
comment
Разве ошибка не сообщает вам исходный файл и номер строки? Опубликуйте полную ошибку.   -  person stark    schedule 09.11.2018
comment
@stark Я обновил сообщение, чтобы включить полную ошибку   -  person Colin Null    schedule 09.11.2018
comment
Я не думаю, что вы можете использовать malloc в модуле ядра.   -  person dbush    schedule 09.11.2018
comment
Вы пытаетесь преобразовать строку только для чтения в верхний регистр.   -  person stark    schedule 09.11.2018
comment
@dbush Вы правы в этом, я собирался исправить эту проблему, как только шифрование и дешифрование будут работать правильно.   -  person Colin Null    schedule 09.11.2018
comment
"key"" является строковым литералом и неизменяем. из cppreference: Attempting to modify a string literal results in undefined behavior. key[i] = key[i] - 'a' + 'A'; ведет себя неопределенно. Кроме того, вы когда-нибудь слышали о strlen ? Используйте составной литерал, чтобы сделать неизменяемым.   -  person KamilCuk    schedule 09.11.2018
comment
Ошибка дешифрования связана с тем, что вы не конвертируете буквы верхнего и нижнего регистра входной строки одинаково. Если ваш ввод в верхнем регистре, расшифровка работает. На мой взгляд, в вашем коде слишком много частных случаев. Например, вам не нужно различать случаи, когда ключ короче, чем ввод; который ловится автоматически. Также неясно, что происходит, когда вы конвертируете символы, которые не являются буквами или пробелами.   -  person M Oehm    schedule 09.11.2018


Ответы (1)


Вы пытаетесь изменить строковый литерал.

Вы вызываете encrypted как:

encrypt("The quick brown fox jumps over lazy dogs","key");

Затем в encrypt вы изменяете второй параметр:

key[i] = key[i] - 'a' + 'A';

Строковые литералы доступны только для чтения, и попытка изменить их вызывает неопределенное поведение.

Сделайте локальную копию key и измените ее при преобразовании верхнего/нижнего регистра.

person dbush    schedule 08.11.2018
comment
Я предполагаю, что выполнение char* keyCopy = key; не сработает, так как это просто создаст указатель на ключ, который по-прежнему является строковым литералом? - person Colin Null; 09.11.2018
comment
@ColinNull Правильно. Вам нужно либо сделать копию key, либо выполнить преобразование верхнего/нижнего регистра при создании fixedKey. - person dbush; 09.11.2018
comment
Сами char* не могут быть изменены? Например, могу ли я создать еще один char* keyCopy, а затем скопировать из ключа символ за символом, а затем изменить keyCopy? Я исправил проблему с регистром ключа, но теперь у меня та же проблема с регистром ввода (его нужно сделать все прописным или строчным), и я хочу избежать изменения возвращаемого типа шифрования и дешифрования, если это возможно. - person Colin Null; 09.11.2018
comment
@ColinNull Зависит от того, на что он указывает. Если он указывает на строковый литерал, вы не можете изменить то, на что он указывает. Если он указывает на элемент массива char или на распределенную память, то вы можете это сделать. - person dbush; 09.11.2018
comment
Итак, тогда следующее будет недействительным? char* inputCpy = NULL; for(i = 0; inputA[i] != '\0'; i++) { inputCpy[i] = input[i]; if(inputCpy[i] >= 'a' && inputCpy[i] <= 'z') { inputCpy[i] = inputCpy[i] - 'a' + 'A'; } } inputCpy[i] = '\0'; - person Colin Null; 09.11.2018
comment
@ColinNull Это недопустимо, потому что inputCpy является указателем NULL. Он должен куда-то указывать. Вы уже используете malloc и локальные массивы, поэтому просто используйте один из этих методов. - person dbush; 09.11.2018