Question

I'm implementing in c the vigenère algorithme.

Unfortunately when testing the program I'm experiencing a segmentation error. I'm compiling with clang on mac.

How could I avoid that error ?

Source Code:

#include <ctype.h>
#include <stdio.h>
#include <string.h>

/**
 * Function: invalidUsage 
 * --------------------
 * Shows usage information and returns 1
 */
int
invalidUsage();

/**
 * Function: cryptCaesar 
 * --------------------
 * Returns encrypted char using caesar cipher
 */
char
cryptCaesar(const char plain, const int key);

/**
 * Function: parseAlphaKey 
 * --------------------
 * Converts an alpha string to a usable key (array of char from 0 to 25) 
 *   Returns true if conversion successful, false if not
 */
bool
parseAlphaKey(const char* input_string, char** output_key);

// === Main ===
int main(int argc, const char *argv[])
{   

    // === Argument validation ===
    char *output_key;

    if (argc != 2
        || !parseAlphaKey(argv[1], &output_key))
        return invalidUsage();

    // === Read plain text ===


    // === Output cipher text ===

    //printf("%s\n", key);
    return 0;
}

int
invalidUsage()
{
    printf("Usage : vigenere <key>\n\n");
    printf("KEY:\n");
    printf("    Must be a string of alpha characters\n");

    return 1;
}

char
cryptCaesar(const char plain, const int key)
{   
    char cipher;

    if (islower(plain)) {
        cipher = (plain - 'a' + key) % 26 + 'a';
    } else if (isupper(plain)) {
        cipher =  (plain - 'A' + key) % 26 + 'A';
    } else {
        cipher = plain;
    }

    return cipher;
}

bool
parseAlphaKey(const char* input_string, char** output_key)
{   
    //output_key = NULL;
    *output_key = malloc(strlen(input_string) * sizeof(char));

    for (int i = 0, n = strlen(input_string); i < n; ++i) {
        if (isupper(input_string[i]))
            *output_key[i] = input_string[i] - 'A';
        else if (islower(input_string[i]))
            *output_key[i] = input_string[i] - 'a';
        else {
            //free(*output_key);
            return false;
        }
    }

    return true;
}

Debug output:

    $ lldb vigenere -- test                                                                                                                                                             
Current executable set to 'vigenere' (x86_64).
(lldb) run
Process 48854 launched: '/Users/.../vigenere' (x86_64)
Process 48854 stopped
* thread #1: tid = 0x549580, 0x0000000100000d9f vigenere`parseAlphaKey(input_string=0x00007fff5fbff941, output_key=0x00007fff5fbff6a8) + 207 at vigenere.c:87, queue = 'com.apple.main-thread, stop reason = EXC_BAD_ACCESS (code=1, address=0x2)
    frame #0: 0x0000000100000d9f vigenere`parseAlphaKey(input_string=0x00007fff5fbff941, output_key=0x00007fff5fbff6a8) + 207 at vigenere.c:87
   84           if (isupper(input_string[i]))
   85               *output_key[i] = input_string[i] - 'A';
   86           else if (islower(input_string[i]))
-> 87               *output_key[i] = input_string[i] - 'a';
   88           else {
   89               //free(*output_key);
   90               return false;
(lldb) kill
Process 48854 exited with status = -1 (0xffffffff) SIGKILL
(lldb) exit

Regards

Was it helpful?

Solution

Two problems:

1) you're not terminating your output string - change:

*output_key = malloc(strlen(input_string) * sizeof(char));

to:

*output_key = malloc(strlen(input_string) + 1);

and make sure you add a '\0' terminator, e.g. in parseAlphaKey add a line:

(*output_key)[n] = '\0';

after the loop.

2) you're getting bitten by operator precedence - change, e.g.

        *output_key[i] = input_string[i] - 'A';

to:

        (*output_key)[i] = input_string[i] - 'A';
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top