-1

Consider this code snippet (simplified syntax for clarity).

void simple (char *bar) {
    char MyArray[12];
    strcpy(MyArray, bar);
}

My instructor says that MyArray can copy at most 12 elements from bar, but from what I've read, MyArray can only store 11 characters because it needs room for the null character at the end. So if the received value of bar is 12 or greater, a buffer overflow would occur. My instructor says that this will only happen if the received value of bar is 13 or greater. Who's right? I'd appreciate if you could cite a credible source so I can convince him.

Akhil Pothana
  • 21
  • 1
  • 4

5 Answers5

5

The definition char MyArray[12] creates an array of 12 char, which can be used to store a string. Since strings in C are null terminated, one of those characters needs to be able to store the null byte at the end of the string.

So a variable of type char [12] can hold a string of at most 11 characters. Attempting to copy a string of length 12 or longer using strcpy as in your example will overflow the bounds of the array.

If you were to use strncpy as follows:

strncpy(MyArray, bar, 12);

This will not overflow the buffer, as it would copy at most 12 characters. However, if 12 characters are copied, that means the string is not null terminated and is therefore not technically a string. Then attempting to use any other string function on MyArray that expect a null terminated string would read off the end of the array.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
dbush
  • 205,898
  • 23
  • 218
  • 273
  • 1
    The question is about `strncpy`. It copies upto `n` bytes and then does not add the terminating null character. An array of 12 chars can hold 12 chars. The null byte is a problem of the person calling strncpy. – Paul Ogilvie Jun 30 '17 at 16:44
  • @PaulOgilvie The title says `strncpy` but the example given uses `strcpy`. I've updated to address both. – dbush Jun 30 '17 at 16:51
  • @PaulOgilvie `strncpy` *does* copy the terminating null character, if it can, that is, if there's room. (But the fact that `strncpy` might or might not copy the terminating null character makes it basically useless.) – Steve Summit Jun 30 '17 at 17:18
  • @SteveSummit You *can* use it, but you need to be disciplined enough to manually add the null terminator after using it. – dbush Jun 30 '17 at 17:22
  • @dbush Thank you, this clarified it for me perfectly. My instructor is adamant that he is correct for some reason even though I've cited the C book Dennis Ritchie wrote himself. This is an intermediate information security class, so maybe he doesn't really know. – Akhil Pothana Jun 30 '17 at 17:34
2

The/a proper use of strncpy would be:

void simple(char *bar) {
    char MyArray[12];
    strncpy(MyArray, bar, sizeof(MyArray)-1);
    MyArray[sizeof(MyArray)-1]= '\0';
}

This just puts in a terminating null character, whether strncpy was able to do that or not.

Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41
0

It's hard to tell, because your question is a bit confusingly worded, but I think you're right, and that your instructor is wrong.

Given the code

void simple(char *bar) {
    char MyArray[12];
    strcpy(MyArray, bar);
}

if the passed-in bar points to a string of 11 or fewer characters, a valid string will be copied to MyArray, with no buffer overflow. But if the string is 12 (or more) characters long, you're right, there'll be a buffer overflow, because strcpy will also copy the 13th, terminating null character.

Earlier you asked about strncpy. Given the code

void simple2(char *bar) {
    char MyArray[12];
    strncpy(MyArray, bar, 12);
}

if the passed-in bar points to a string of 11 or fewer characters, a valid string will be copied to MyArray. But if the string is 12 characters long, we have a different problem. strncpy will copy 12 characters and stop, meaning that it won't copy the terminating null character. There won't be a buffer overflow, but MyArray still won't end up containing a valid string.

Also, you asked for a credible source. I wrote the C FAQ list -- would you consider that credible? :-)

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
0

My instructor says that MyArray can copy at most 12 elements from bar

It will be more correctly to say that the array MyArray may accomodate at most 12 elements of the array bar. Otherwise there will be an attempt to access memory beyond the array.

So in fact your instructor is right.

The array MyArray is declared having only 12 elements

char MyArray[12];

but from what I've read, MyArray can only store 11 characters because it needs room for the null character at the end

The terminating zero is also a character. And the function strcpy copies all characters from the source string including the terminating zero that is present in the source string.

So if the received value of bar is 12 or greater, a buffer overflow would occur

What does mean the magic number 12 in this context? is it the number of characters in the array bar or it is the length of the string stored in the array bar (that used as an argument is converted to pointer to its first element)?

If the number 12 means the size of the string stored in the array bar then the function strcpy will try to copy all characters of the array including the terminating zero and in this case the array MyArray has to be declared as having 13 elements.

char MyArray[13];

However if the number 12 means the number of elements in the array bar (used as an argument of the function) and it contains a string then the length of the string is evidently is less than 12. So the array MyArray can accept all characters of the source array including the terminating zero.

So the reason for the confusion is that you did not make a common conclusion what the number 12 means whether it is the length of the source string or it is the size of the source array.

In the first case there will be indeed undefined behavior.

In the second case if the source array contains a string then the code will be well-formed.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

A char array and string are similar, but not the same.

In C,

A string is a contiguous sequence of characters terminated by and including the first null character. C11dr §7.1.1 1


void simple (char *bar) {
    char MyArray[12];
    strcpy(MyArray, bar);
}

My instructor says that MyArray can copy at most 12 elements from bar,

This is correct: MyArray[] can receive up to 12 characters.

strcpy() copies the memory, starting at bar to the array MyArray[] and continues until it copies a null character. If more that 12 characters (the count of 12 includes the null character) are attempted to be copied, the result is undefined behavior (UB).

MyArray can only store 11 characters

Not quite. MyArray[] can store 12 characters. To treat that data as a string, a null character must be one of those 12. When interpreted as a string, the string include all the characters up to the null character. It also include the null chracter. Each element of MyArray[] could be an 'x', but then that memory would not be a string as it lacks a null character.

So if the received value of bar is 12 or greater, a buffer overflow would occur.

Not quite. If the strcpy() attempts to write outside MyArray[], the result is undefined. Buffer overflow may occur. The program may stop, etc. The result is not defined. It is undefined behavior.

My instructor says that this will only happen if the received value of bar is 13 or greater.

bar is a pointer - it likely does not have a "value of 13". bar likely points to memory that is a string. A string includes its terminating null character, so the string may consists of 12 non-null characters and a final null character for a total of 13 characters. MyArray[] is insufficient to store a copy of that string.

Who's right?

I suspect the dis-connect is in the imprecise meaning of "bar is 13"`. I see nothing the reported by the instructor as incorrect.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256