Search code examples
cstructgdbmemset

"memset"ting a struct causes printf to print struct member longer than its limit


I observed this issue in a very large C program.

The structure declaration is:

struct kc910InputParms {
    char inStream[71];
}

In the program, when there is memset operation done on this struct variable, the printf statement prints longer than its limit(i.e. 71 characters is the limit). Please see below the output obtained while debugging in gdb.

(gdb) s
cpyInParmsToCbl (in=0xffffb9f6, out=0x80ef320) at kc190Common.c:456
456       memset((void*)out, ' ', sizeof(kc910InputParms));
(gdb) printf "<%s>\n", out.inStream
<>
(gdb) n
458       strncpy(out->inStream+16, in->system_id,strlen(in->system_id));
(gdb) printf "<%s>\n", out.inStream
<                                                                       Pending>

Please notice above: There are 7 extra characters appended as "Pending" which prints the out.inStream upto 78 characters. This introduces flaw in the subsequent stage of the program.

Can someone please help me to understand this behavior and the correct way to use memset (if I am doing it wrong)?

If this is happening because the variable out.inStream has not been terminated by a null character '\0', then my question is: Why it didn't print in the same way before memset ?


Solution

  • It is due to the missing terminating nul. The reason why it worked before was due to the compiler setting the memory area to nuls, or just random luck.

    You are also telling strncpy that there is space only for as many bytes as there are characters in the string so it is not adding the terminator. This is the wrong way to do it. You should tell strncpy how many bytes are available in the destination, not how many characters are in the source. In this case 54 (70-16). And you should explicitly set the last byte to nul for the case where the source is longer than 54 characters.

    printf and other C string functions don't know anything about array sizes or memory allocations, they go by the terminating nul. So if you don't have it, they will continue until they find one, perhaps running out of the allocated memory space and causing undefined behavior. That is why you get more than 71 characters in output.