Search code examples
ckernighan-and-ritchie

K&R 2-3 htoi segmentation fault


Hi this is my first question here so I apologize if I didn't follow all the rules for posting. This is K&R exercise 2-3 and I'm getting a segmentation fault when compiling with GCC and I'm not familiar with the debugger to understand what's going on. I'd be grateful if anyone could glance over the code and help me with what went wrong.

#include <stdio.h>

#define HEX 16

unsigned int htoi(char s[]) {
    int i, len, n, rp, v;
    v = 0;

    if (s[0] == '0')
        if (s[1] == 'x' || s[1] == 'X')
           s[1] = '0';
    for (len = 0; len != '\0'; ++len) {
    }
    for (i = len; i >= 0; --i) {
        if (s[i] >= '0' && s[i] <= '9')
            n = s[i] - '0';
        else if (s[i] >= 'A' && s[i] <= 'F')
            n = s[i] - 'A' + 10;
        else if (s[i] >= 'a' && s[i] <= 'f')
            n = s[i] - 'a' + 10;

        rp = len - i;
        v += n * HEX^rp;
    }
    return v;
}

int main() {
    int test = htoi("0x1a9f");
    printf("%d\n", test);
    return 0;
}

Solution

  • int test = htoi("0x1a9f");
    

    passes the string literal "0x1a9f" to htoi. This may exist in read-only memory and cannot be modified. You therefore get undefined behaviour (with a crash a valid example of this) when you try to write to the string in the line

    s[1] = '0';
    

    The easiest fix is to copy the original string into a modifiable variable

    char s[] = "0x1a9f";
    int test = htoi(s);
    

    As reported by Grijesh, further into htoi, you also read beyond the bounds of the string

    for (i = len; i >= 0; --i) 
    

    should be:

    for (i = len - 1; i >= 0; --i)