summaryrefslogtreecommitdiff
path: root/util/libreboot-utils/lib
diff options
context:
space:
mode:
Diffstat (limited to 'util/libreboot-utils/lib')
-rw-r--r--util/libreboot-utils/lib/string.c151
1 files changed, 113 insertions, 38 deletions
diff --git a/util/libreboot-utils/lib/string.c b/util/libreboot-utils/lib/string.c
index ea7ca30a..0329c6c3 100644
--- a/util/libreboot-utils/lib/string.c
+++ b/util/libreboot-utils/lib/string.c
@@ -14,25 +14,12 @@
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
+#include <limits.h>
+#include <stdint.h>
#include "../include/common.h"
-/* scmp() - strict string comparison
- *
- * strict string comparison
- * similar to strncmp, but null and
- * unterminated inputs do not produce
- * a return value; on error, errno is
- * set and -1 is returned.
- *
- * the real return value is stored in
- * the 4th argument by pointer.
- *
- * the value at rval pointer is set,
- * only upon success. callers should
- * check the return value accordingly.
- */
-
+/* strict strcmp */
int
scmp(const char *a,
const char *b,
@@ -46,9 +33,8 @@ scmp(const char *a,
if (a == NULL ||
b == NULL ||
rval == NULL) {
-
errno = EFAULT;
- return -1;
+ goto err;
}
for (ch = 0; ch < maxlen; ch++) {
@@ -67,27 +53,14 @@ scmp(const char *a,
}
}
- /* block unterminated strings */
+err:
errno = EFAULT;
+ if (rval != NULL)
+ *rval = -1;
return -1;
}
-/* slen() - strict strict length
- *
- * strict string length calculation
- * similar to strnlen, but null and
- * unterminated inputs do not produce
- * a return value; on error, errno is
- * set and -1 is returned.
- *
- * the real return value is stored in
- * the 3rd argument by pointer.
- *
- * the value at rval pointer is set,
- * only upon success. callers should
- * check the return value accordingly.
- */
-
+/* strict strlen */
int
slen(const char *s,
size_t maxlen,
@@ -97,9 +70,8 @@ slen(const char *s,
if (s == NULL ||
rval == NULL) {
-
errno = EFAULT;
- return -1;
+ goto err;
}
for (ch = 0;
@@ -109,11 +81,114 @@ slen(const char *s,
if (ch == maxlen) {
/* unterminated */
errno = EFAULT;
- return -1;
+ goto err;
}
*rval = ch;
return 0;
+err:
+ if (rval != NULL)
+ *rval = 0;
+ return -1;
+}
+
+/* strict strdup */
+int
+sdup(const char *s,
+ size_t n, char **dest)
+{
+ size_t size;
+ char *rval;
+
+ if (dest == NULL ||
+ slen(s, n, &size) < 0 ||
+ if_err(size == SIZE_MAX, EOVERFLOW) ||
+ (rval = malloc(size + 1)) == NULL) {
+
+ if (dest != NULL)
+ *dest = NULL;
+ return -1;
+ }
+
+ memcpy(rval, s, size);
+ *(rval + size) = '\0';
+
+ *dest = rval;
+ return 0;
+}
+
+/* strict strcat */
+int
+scat(const char *s1, const char *s2,
+ size_t n, char **dest)
+{
+ size_t size1;
+ size_t size2;
+ char *rval;
+
+ if (dest == NULL ||
+ slen(s1, n, &size1) < 0 ||
+ slen(s2, n, &size2) < 0 ||
+ if_err(size1 > SIZE_MAX - size2 - 1, EOVERFLOW) ||
+ (rval = malloc(size1 + size2 + 1)) == NULL) {
+
+ if (dest != NULL)
+ *dest = NULL;
+ return -1;
+ }
+
+ memcpy(rval, s1, size1);
+ memcpy(rval + size1, s2, size2);
+ *(rval + size1 + size2) = '\0';
+
+ *dest = rval;
+ return 0;
+}
+
+/* strict split/de-cat - off is where
+ 2nd buffer will start from */
+int
+dcat(const char *s, size_t n,
+ size_t off, char **dest1,
+ char **dest2)
+{
+ size_t size;
+ char *rval1 = NULL;
+ char *rval2 = NULL;
+
+ if (dest1 == NULL || dest2 == NULL ||
+ slen(s, n, &size) < 0 ||
+ if_err(size == SIZE_MAX, EOVERFLOW) ||
+ if_err(off >= size, EOVERFLOW) ||
+ (rval1 = malloc(off + 1)) == NULL ||
+ (rval2 = malloc(size - off + 1)) == NULL) {
+
+ goto err;
+ }
+
+ memcpy(rval1, s, off);
+ *(rval1 + off) = '\0';
+
+ memcpy(rval2, s + off, size - off);
+ *(rval2 + size - off) = '\0';
+
+ *dest1 = rval1;
+ *dest2 = rval2;
+
+ return 0;
+
+err:
+ if (rval1 != NULL)
+ free(rval1);
+ if (rval2 != NULL)
+ free(rval2);
+
+ if (dest1 != NULL)
+ *dest1 = NULL;
+ if (dest2 != NULL)
+ *dest2 = NULL;
+
+ return -1;
}
/* the one for nvmutil state is in state.c */