summaryrefslogtreecommitdiff
path: root/util/libreboot-utils/lib/string.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/libreboot-utils/lib/string.c')
-rw-r--r--util/libreboot-utils/lib/string.c152
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;