2

While working through exercise 3-5 in The C Programming Language, I've come across the following unexpected behavior.

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

// inspired by: http://www.eng.uerj.br/~fariasol/disciplinas/LABPROG/C_language/Kernighan_and_Ritchie/solved-exercises/solved-exercises.html/krx305.html

void reverse(char s[]) {
    int c, i, j;
    for ( i = 0, j = strlen(s)-1; i < j; i++, j--) {
        c = s[i];
        s[i] = s[j];
        s[j] = c;
    }
}

void itob(int n, char s[], int b) {
    static char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    int i = 0,
        sign;

    if ( b < 2 || b > 36 ) {
        fprintf(stderr, "EX3_5: Cannot support base %d\n", b);
    }

    if ((sign = n) < 0) {
        n = -n;
    }

    do {
        s[i++] = digits[n % b];
    } while (n /= b);

    if (sign < 0) {
        s[i++] = '-';
    }

    s[i] = '\0';

    reverse(s);
}

int main() {
    int base = 2,
        input;
    char buffer[5] = "0000";

    input = 127;
    itob(input, buffer, base);
    printf("%d in base %d is %s\n", input, base, buffer);
    // 127 in base 2 is 1111111

    input = 128;
    itob(input, buffer, base);
    printf("%d in base %d is %s\n", input, base, buffer);
    // 0 in base 2 is 10000000
    // Why is input now 0?!

    return 0;
}

Why is the value of the input variable being changed (only when input is greater than 127)? I'm new to C but this seems very unexpected. As far as I understand, function arguments are pass-by-value.

pdoherty926
  • 9,895
  • 4
  • 37
  • 68
  • 4
    `buffer` isn't big enough. You've got a buffer overflow and undefined behavior. – user2357112 Feb 21 '17 at 04:34
  • array function parameters are adjusted to be pointer parameters. While the pointers are pass by value, they can be used to access the memory of the caller. – M.M Feb 21 '17 at 04:34
  • @user2357112 Thank you - that was it. If you add your comment as an answer, I'd be happy to accept it. – pdoherty926 Feb 21 '17 at 04:36

2 Answers2

5

Your buffer isn't big enough. You allocated space for 4 chars and a null terminator:

char buffer[5] = "0000";

but you're trying to stuff 8 chars and a null terminator in there with itob(input, buffer, base);. That leads to a buffer overflow and undefined behavior.

user2357112
  • 260,549
  • 28
  • 431
  • 505
2

Try to use larger buffersize, with only 4 chars you can't convert number larger than 127.

Ruslan Skaldin
  • 981
  • 16
  • 29