I suppose this strlcpy4 without a goto is more elegant -Luke
On Tue, Jun 30, 2020 at 10:07 PM Luke Small <lukensm...@gmail.com> wrote: > I made it SUPER easy to test my assertion. The code is there. No > configuration needed. > > On Tue, Jun 30, 2020 at 9:59 PM Theo de Raadt <dera...@openbsd.org> wrote: > >> Luke Small <lukensm...@gmail.com> wrote: >> >> > So did you run the program on one of those? >> >> Why would I? >> >> i see a sales pitch >> >> and i go BULLSHIT >> >> and I'm done >> >> -- > -Luke >
#include <unistd.h> #include <stdlib.h> #include <string.h> #include <stdio.h> #include <err.h> #include <sys/param.h> /* cc strlcpy_test.c -pipe -O2 -o strlcpy_test && ./strlcpy_testfast */ /* * Copy string src to buffer dst of size dsize. At most dsize-1 * chars will be copied. Always NUL terminates (unless dsize == 0). * Returns strlen(src); if retval >= dsize, truncation occurred. */ static size_t strlcpy0(char *dst, const char *src, size_t dsize) { const char *osrc = src; size_t nleft = dsize; /* Copy as many bytes as will fit. */ if (nleft != 0) { while (--nleft != 0) { if ((*dst++ = *src++) == '\0') break; } } /* Not enough room in dst, add NUL and traverse rest of src. */ if (nleft == 0) { if (dsize != 0) *dst = '\0'; /* NUL-terminate dst */ while (*src++) ; } return(src - osrc - 1); /* count does not include NUL */ } static size_t strlcpy3(char *dst, const char *src, size_t dsize) { const char *osrc = src; size_t nleft = dsize; if (nleft != 0) { /* Copy as many bytes as will fit. */ while (--nleft != 0) if ((*dst++ = *src++) == '\0') return(src - osrc - 1); *dst = '\0'; } /* Not enough room in dst, traverse rest of src. */ while (*src++) ; return(src - osrc - 1); /* count does not include NUL */ } static size_t strlcpy4(char dst[], const char src[], size_t dsize) { const char *osrc = src; size_t nleft = dsize; if (nleft != 0) { if (--nleft == 0) { *dst = '\0'; /* NUL-terminate dst */ if (*src == '\0') return 0; } else { /* Copy as many bytes as will fit. */ if ((*dst = *src) == '\0') return 0; while (--nleft != 0) if ((*++dst = *++src) == '\0') return(src - osrc); dst[1] = '\0'; /* NUL-terminate dst */ } } else if (*src == '\0') return 0; /* Not enough room in dst, traverse rest of src. */ while (*++src) ; return(src - osrc); /* count does not include NUL */ } int main() { long double cpu_time_used; size_t y; struct timespec tv_start, tv_end; char *buffer, *buffer2; size_t n = 50000; size_t m = n + 50; buffer = malloc(m); if (buffer == NULL) err(1, "malloc"); buffer2 = malloc(n); if (buffer2 == NULL) err(1, "malloc"); /* no intermediate '\0' */ for (y = 0; y < m; ++y) buffer[y] = arc4random_uniform(255) + 1; buffer[m - 1] = '\0'; clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tv_start); strlcpy(buffer2, buffer, n); clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tv_end); cpu_time_used = (long double) (tv_end.tv_sec - tv_start.tv_sec) + (long double) (tv_end.tv_nsec - tv_start.tv_nsec) / (long double) 1000000000; printf("\n\nstrlcpy\n"); printf("time = %.9Lf\n\n\n", cpu_time_used); clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tv_start); strlcpy0(buffer2, buffer, n); clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tv_end); cpu_time_used = (long double) (tv_end.tv_sec - tv_start.tv_sec) + (long double) (tv_end.tv_nsec - tv_start.tv_nsec) / (long double) 1000000000; printf("\n\nstrlcpy0\n"); printf("time = %.9Lf\n\n\n", cpu_time_used); clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tv_start); strlcpy3(buffer2, buffer, n); clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tv_end); cpu_time_used = (long double) (tv_end.tv_sec - tv_start.tv_sec) + (long double) (tv_end.tv_nsec - tv_start.tv_nsec) / (long double) 1000000000; printf("\n\nstrlcpy3\n"); printf("time = %.9Lf\n\n\n", cpu_time_used); clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tv_start); strlcpy4(buffer2, buffer, n); clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tv_end); cpu_time_used = (long double) (tv_end.tv_sec - tv_start.tv_sec) + (long double) (tv_end.tv_nsec - tv_start.tv_nsec) / (long double) 1000000000; printf("\n\nstrlcpy4\n"); printf("time = %.9Lf\n\n\n", cpu_time_used); return 0; }