/* * Compile with: gcc -Wall -Wextra -O2 -g2 -ggdb strncpy_crlf_tst.c -o strncpytst */ #include #include #include static void strncpy_crlf (char *dest, const char *src, size_t destmax, size_t srcmax) { char * destend = dest + destmax - 1 ; const char * srcend = src + srcmax ; while (dest < destend && src < srcend) { if ((src [0] == '\r' && src [1] == '\n') || (src [0] == '\n' && src [1] == '\r')) { *dest++ = '\r' ; *dest++ = '\n' ; src += 2 ; continue ; } ; if (src [0] == '\r') { *dest++ = '\r' ; *dest++ = '\n' ; src += 1 ; continue ; } ; if (src [0] == '\n') { *dest++ = '\r' ; *dest++ = '\n' ; src += 1 ; continue ; } ; *dest++ = *src++ ; } ; /* Make sure dest is terminated. */ *dest = 0 ; } /* strncpy_crlf */ union u { char buf[16]; char ebuf[20]; }; struct a { char buf[16]; }; int main() { union u x; memset(&x.ebuf, 1, sizeof(x.ebuf)); assert(x.ebuf[0] == 1); assert(x.ebuf[sizeof(x.buf)] == 1); static const char nl[] = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; /* * Overrun the declared bounds of x.buf, demonstrated via an assert * a few lines later. */ strncpy_crlf(x.buf, nl, sizeof(x.buf), sizeof(nl)); /* * Overrun a stack buffer by one byte, demonstrated via Valgrind * memcheck. */ struct a *y = malloc(sizeof(struct a)); strncpy_crlf(y->buf, nl, sizeof(y->buf), sizeof(nl)); assert(x.ebuf[sizeof(x.buf)] == 1); free(y); return 0; }