diff options
Diffstat (limited to 'util/libreboot-utils/lib/string.c')
| -rw-r--r-- | util/libreboot-utils/lib/string.c | 152 |
1 files changed, 91 insertions, 61 deletions
diff --git a/util/libreboot-utils/lib/string.c b/util/libreboot-utils/lib/string.c index d5e2de85..49c23663 100644 --- a/util/libreboot-utils/lib/string.c +++ b/util/libreboot-utils/lib/string.c @@ -19,6 +19,20 @@ #include "../include/common.h" +void +free_and_set_null(char **buf) +{ + if (buf == NULL) + err_exit(EFAULT, + "null ptr (to ptr for freeing) in free_and_set_null"); + + if (*buf == NULL) + return; + + free(*buf); + *buf = NULL; +} + /* safe(ish) malloc. use this and free_and_set_null() @@ -160,49 +174,46 @@ sdup(const char *s, } /* concatenate N number of strings */ -/* slen already checks null/termination */ int scatn(ssize_t sc, const char **sv, size_t max, char **rval) { - ssize_t i = 0; - - size_t ts = 0; - size_t *size = NULL; - - char *ct = NULL; int saved_errno = errno; - - if (if_err(sc <= 0, EINVAL) || - if_err(sc > SIZE_MAX / sizeof(size_t), EOVERFLOW) || - if_err(sv == NULL, EINVAL)) + char *final = NULL; + char *rcur = NULL; + char *rtmp = NULL; + size_t i; + + if (if_err(sc < 2, EINVAL) || + if_err(sv == NULL, EFAULT) || + if_err(rval == NULL || *rval != NULL, EFAULT)) goto err; - vmalloc((void **)&size, sizeof(size_t) * sc); + for (i = 0; i < sc; i++) { - for (i = 0; i < sc; i++, ts += size[i]) - if (if_err(sv[i] == NULL, EINVAL) || - slen(sv[i], max, &size[i]) < 0 || - if_err(size[i] > max - 1, EOVERFLOW) || - if_err((size[i] + ts) < ts, EOVERFLOW)) + if (if_err(sv[i] == NULL, EFAULT)) goto err; + else if (i == 0) { + if (sdup(sv[0], max, &final) < 0) + goto err; + continue; + } - if (if_err(ts > SIZE_MAX - 1, EOVERFLOW) || - if_err(ts > max - 1, EOVERFLOW)) - goto err; - - smalloc(&ct, ts + 1); - for (ts = i = 0; i < sc; i++, ts += size[i]) - memcpy(ct + ts, sv[i], size[i]); + rtmp = NULL; + if (scat(final, sv[i], max, &rtmp) < 0) + goto err; - *(ct + ts) = '\0'; - *rval = ct; + free_and_set_null(&final); + final = rtmp; + rtmp = NULL; + } - errno = saved_errno; + *rval = final; return 0; err: - free_and_set_null(&ct); - free_and_set_null((char **)&size); + free_and_set_null(&rcur); + free_and_set_null(&rtmp); + free_and_set_null(&final); return set_errno(saved_errno, EFAULT); } @@ -216,7 +227,7 @@ scat(const char *s1, const char *s2, size_t size2; char *rval = NULL; - if (dest == NULL || + if (if_err(dest == NULL || *dest != NULL, EFAULT) || slen(s1, n, &size1) < 0 || slen(s2, n, &size2) < 0 || if_err(size1 > SIZE_MAX - size2 - 1, EOVERFLOW)) { @@ -281,6 +292,39 @@ err: return -1; } +/* because no libc reimagination is complete + * without a reimplementation of memcmp. and + * no safe one is complete without null checks. + */ +int +vcmp(const void *s1, const void *s2, size_t n) +{ + size_t i = 0; + size_t a; + size_t b; + + if (if_err(s1 == NULL || s2 == NULL, EFAULT)) + err_exit(EFAULT, "vcmp: null input"); + + const unsigned char *x = s1; + const unsigned char *y = s2; + + for ( ; i + sizeof(size_t) <= n; i += sizeof(size_t)) { + + memcpy(&a, x + i, sizeof(size_t)); + memcpy(&b, y + i, sizeof(size_t)); + + if (a != b) + break; + } + + for ( ; i < n; i++) + if (x[i] != y[i]) + return (int)x[i] - (int)y[i]; + + return 0; +} + /* on functions that return with errno, * i sometimes have a default fallback, * which is set if errno wasn't changed, @@ -310,17 +354,13 @@ err_exit(int nvm_errval, const char *msg, ...) if (!errno) saved_errno = errno = ECANCELED; - if ((p = lbgetprogname()) != NULL) - fprintf(stderr, "%s: ", p); + fprintf(stderr, "%s: ", lbgetprogname()); va_start(args, msg); vfprintf(stderr, msg, args); va_end(args); - if (p != NULL) - fprintf(stderr, ": %s\n", strerror(errno)); - else - fprintf(stderr, "%s\n", strerror(errno)); + fprintf(stderr, ": %s\n", strerror(errno)); exit(EXIT_FAILURE); } @@ -359,22 +399,16 @@ no_op(void) const char * lbgetprogname(void) { - static char *rval = NULL; - static char *p; - static int setname = 0; - - if (!setname) { - if ((rval = lbsetprogname(NULL)) == NULL) - return NULL; - - p = strrchr(rval, '/'); - if (p) - rval = p + 1; - - setname = 1; - } - - return rval; + char *name = lbsetprogname(NULL); + char *p = NULL; + if (name) + p = strrchr(name, '/'); + if (p) + return p + 1; + else if (name) + return name; + else + return "libreboot-utils"; } /* singleton. if string not null, @@ -385,17 +419,13 @@ lbgetprogname(void) char * lbsetprogname(char *argv0) { - static int setname = 0; static char *progname = NULL; - size_t len; - - if (!setname) { - if (if_err(argv0 == NULL || *argv0 == '\0', EFAULT) || - slen(argv0, 4096, &len) < 0) - return NULL; + static int set = 0; - memcpy(smalloc(&progname, len + 1), argv0, len + 1); - setname = 1; + if (!set) { + if (argv0 == NULL || sdup(argv0, 4096, &progname) < 0) + return "libreboot-utils"; + set = 1; } return progname; |
