mirror of
https://codeberg.org/libreboot/lbmk.git
synced 2026-07-11 05:52:36 +02:00
lbutils: strict string functions - abort on err
on the conditions where these functions encounter an unexpected error, we currently return -1 this means that the caller must check. which means the caller won't check. nobody does. i often forget. force the caller (me) to be correct, instead. the current calling convention is that the real return value is stored in a pointer, provided inside the function signature, on a given string function, and the function's return value is merely an indicator. this calling convention is retained for now; the next patch will change it, such that the real value is also the function's return value. this is more flexible. Signed-off-by: Leah Rowe <leah@libreboot.org>
This commit is contained in:
@@ -24,17 +24,25 @@
|
||||
*/
|
||||
#define ff ((size_t)-1 / 0xFF)
|
||||
#define high ((ff) * 0x80)
|
||||
/* NOTE:
|
||||
* do not assume that a match means
|
||||
* both words have null at the same
|
||||
* location. see how this is handled
|
||||
* e.g. in scmp.
|
||||
*/
|
||||
#define zeroes(x) (((x) - (ff)) & ~(x) & (high))
|
||||
|
||||
size_t
|
||||
page_remain(const void *p)
|
||||
{
|
||||
/* calling sysconf repeatedly
|
||||
* is folly. cache it (static)
|
||||
*/
|
||||
static size_t pagesz = 0;
|
||||
if (!pagesz)
|
||||
pagesz = pagesize(),
|
||||
pagesz -= ((uintptr_t)p & (pagesz - 1));
|
||||
pagesz = (size_t)pagesize();
|
||||
|
||||
return pagesz;
|
||||
return pagesz - ((uintptr_t)p & (pagesz - 1));
|
||||
}
|
||||
|
||||
long
|
||||
@@ -122,49 +130,56 @@ scmp(const char *a,
|
||||
size_t j;
|
||||
size_t wa;
|
||||
size_t wb;
|
||||
int saved_errno = errno;
|
||||
|
||||
if (a == NULL ||
|
||||
b == NULL ||
|
||||
rval == NULL) {
|
||||
errno = EFAULT;
|
||||
if (if_err(a == NULL || b == NULL || rval == NULL, EFAULT))
|
||||
goto err;
|
||||
}
|
||||
|
||||
for ( ; ((uintptr_t)(a + i) % sizeof(size_t)) != 0; i++) {
|
||||
|
||||
if (i >= maxlen)
|
||||
if (if_err(i >= maxlen, EOVERFLOW))
|
||||
goto err;
|
||||
else if (!ccmp(a, b, i, rval))
|
||||
return 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for ( ; i + sizeof(size_t) <= maxlen;
|
||||
i += sizeof(size_t)) {
|
||||
|
||||
/* prevent crossing page boundary on word check */
|
||||
if (page_remain(a + i) < sizeof(size_t) ||
|
||||
page_remain(b + i) < sizeof(size_t))
|
||||
break;
|
||||
|
||||
memcpy(&wa, a + i, sizeof(size_t));
|
||||
memcpy(&wb, b + i, sizeof(size_t));
|
||||
|
||||
if (wa != wb)
|
||||
for (j = 0; j < sizeof(size_t); j++)
|
||||
if (!ccmp(a, b, i + j, rval))
|
||||
return 0;
|
||||
goto out;
|
||||
|
||||
if (!zeroes(wa))
|
||||
continue;
|
||||
|
||||
*rval = 0;
|
||||
return 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for ( ; i < maxlen; i++)
|
||||
if (!ccmp(a, b, i, rval))
|
||||
return 0;
|
||||
goto out;
|
||||
|
||||
err:
|
||||
errno = EFAULT;
|
||||
(void) set_errno(saved_errno, EFAULT);
|
||||
if (rval != NULL)
|
||||
*rval = -1;
|
||||
|
||||
err_exit(errno, "scmp");
|
||||
return -1;
|
||||
out:
|
||||
errno = saved_errno;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ccmp(const char *a, const char *b,
|
||||
@@ -173,9 +188,8 @@ int ccmp(const char *a, const char *b,
|
||||
unsigned char ac;
|
||||
unsigned char bc;
|
||||
|
||||
if (if_err(a == NULL || b == NULL, EFAULT) ||
|
||||
rval == NULL)
|
||||
return -1;
|
||||
if (if_err(a == NULL || b == NULL || rval == NULL, EFAULT))
|
||||
err_exit(errno, "ccmp");
|
||||
|
||||
ac = (unsigned char)a[i];
|
||||
bc = (unsigned char)b[i];
|
||||
@@ -197,15 +211,13 @@ slen(const char *s,
|
||||
size_t maxlen,
|
||||
size_t *rval)
|
||||
{
|
||||
int saved_errno = errno;
|
||||
size_t i = 0;
|
||||
size_t w;
|
||||
size_t j;
|
||||
|
||||
if (s == NULL ||
|
||||
rval == NULL) {
|
||||
errno = EFAULT;
|
||||
if (if_err(s == NULL || rval == NULL, EFAULT))
|
||||
goto err;
|
||||
}
|
||||
|
||||
for ( ; ((uintptr_t)(s + i) % sizeof(size_t)) != 0; i++) {
|
||||
|
||||
@@ -213,7 +225,7 @@ slen(const char *s,
|
||||
goto err;
|
||||
if (s[i] == '\0') {
|
||||
*rval = i;
|
||||
return 0;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,14 +233,13 @@ slen(const char *s,
|
||||
i += sizeof(size_t)) {
|
||||
|
||||
memcpy(&w, s + i, sizeof(size_t));
|
||||
|
||||
if (!zeroes(w))
|
||||
continue;
|
||||
|
||||
for (j = 0; j < sizeof(size_t); j++) {
|
||||
if (s[i + j] == '\0') {
|
||||
*rval = i + j;
|
||||
return 0;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -236,15 +247,20 @@ slen(const char *s,
|
||||
for ( ; i < maxlen; i++) {
|
||||
if (s[i] == '\0') {
|
||||
*rval = i;
|
||||
return 0;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
err:
|
||||
errno = EFAULT;
|
||||
(void) set_errno(saved_errno, EFAULT);
|
||||
if (rval != NULL)
|
||||
*rval = 0;
|
||||
|
||||
err_exit(errno, "slen");
|
||||
return -1;
|
||||
out:
|
||||
errno = saved_errno;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* strict word-based strdup */
|
||||
@@ -256,21 +272,22 @@ sdup(const char *s,
|
||||
size_t w;
|
||||
size_t i = 0;
|
||||
char *out = NULL;
|
||||
int saved_errno = errno;
|
||||
|
||||
if (dest == NULL || *dest != NULL || s == NULL)
|
||||
if (if_err(dest == NULL || *dest != NULL || s == NULL, EFAULT))
|
||||
goto err;
|
||||
|
||||
out = smalloc(dest, max);
|
||||
|
||||
for ( ; ((uintptr_t)(s + i) % sizeof(size_t)) != 0; i++) {
|
||||
|
||||
if (i >= max)
|
||||
if (if_err(i >= max, EOVERFLOW))
|
||||
goto err;
|
||||
|
||||
out[i] = s[i];
|
||||
if (s[i] == '\0') {
|
||||
*dest = out;
|
||||
return 0;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,7 +307,7 @@ sdup(const char *s,
|
||||
out[i + j] = s[i + j];
|
||||
if (s[i + j] == '\0') {
|
||||
*dest = out;
|
||||
return 0;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -300,7 +317,7 @@ sdup(const char *s,
|
||||
out[i] = s[i];
|
||||
if (s[i] == '\0') {
|
||||
*dest = out;
|
||||
return 0;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,8 +325,14 @@ err:
|
||||
free_and_set_null(&out);
|
||||
if (dest != NULL)
|
||||
*dest = NULL;
|
||||
errno = EFAULT;
|
||||
|
||||
(void) set_errno(saved_errno, EFAULT);
|
||||
err_exit(errno, "sdup");
|
||||
|
||||
return -1;
|
||||
out:
|
||||
errno = saved_errno;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* concatenate N number of strings */
|
||||
@@ -347,6 +370,7 @@ scatn(ssize_t sc, const char **sv,
|
||||
rtmp = NULL;
|
||||
}
|
||||
|
||||
errno = saved_errno;
|
||||
*rval = final;
|
||||
return 0;
|
||||
err:
|
||||
@@ -354,7 +378,10 @@ err:
|
||||
free_and_set_null(&rtmp);
|
||||
free_and_set_null(&final);
|
||||
|
||||
return set_errno(saved_errno, EFAULT);
|
||||
(void) set_errno(saved_errno, EFAULT);
|
||||
|
||||
err_exit(errno, "scatn");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* strict strcat */
|
||||
@@ -365,16 +392,16 @@ scat(const char *s1, const char *s2,
|
||||
size_t size1;
|
||||
size_t size2;
|
||||
char *rval = NULL;
|
||||
int saved_errno = errno;
|
||||
|
||||
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)) {
|
||||
if (if_err(dest == NULL || *dest != NULL, EFAULT))
|
||||
goto err;
|
||||
|
||||
if (dest != NULL)
|
||||
*dest = NULL;
|
||||
return -1;
|
||||
}
|
||||
slen(s1, n, &size1);
|
||||
slen(s2, n, &size2);
|
||||
|
||||
if (if_err(size1 > SIZE_MAX - size2 - 1, EOVERFLOW))
|
||||
goto err;
|
||||
|
||||
memcpy(smalloc(&rval, size1 + size2 + 1),
|
||||
s1, size1);
|
||||
@@ -382,7 +409,15 @@ scat(const char *s1, const char *s2,
|
||||
*(rval + size1 + size2) = '\0';
|
||||
|
||||
*dest = rval;
|
||||
errno = saved_errno;
|
||||
return 0;
|
||||
err:
|
||||
(void) set_errno(saved_errno, EINVAL);
|
||||
if (dest != NULL)
|
||||
*dest = NULL;
|
||||
err_exit(errno, "scat");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* strict split/de-cat - off is where
|
||||
@@ -395,14 +430,16 @@ dcat(const char *s, size_t n,
|
||||
size_t size;
|
||||
char *rval1 = NULL;
|
||||
char *rval2 = NULL;
|
||||
int saved_errno = errno;
|
||||
|
||||
if (dest1 == NULL || dest2 == NULL ||
|
||||
slen(s, n, &size) < 0 ||
|
||||
if_err(size == SIZE_MAX, EOVERFLOW) ||
|
||||
if_err(off >= size, EOVERFLOW)) {
|
||||
|
||||
if (if_err(dest1 == NULL || dest2 == NULL, EFAULT))
|
||||
goto err;
|
||||
|
||||
slen(s, n, &size);
|
||||
|
||||
if (if_err(size >= SIZE_MAX - 1, EOVERFLOW) ||
|
||||
if_err(off >= size, EOVERFLOW))
|
||||
goto err;
|
||||
}
|
||||
|
||||
memcpy(smalloc(&rval1, off + 1),
|
||||
s, off);
|
||||
@@ -415,6 +452,7 @@ dcat(const char *s, size_t n,
|
||||
*dest1 = rval1;
|
||||
*dest2 = rval2;
|
||||
|
||||
errno = saved_errno;
|
||||
return 0;
|
||||
|
||||
err:
|
||||
@@ -423,6 +461,9 @@ err:
|
||||
free_and_set_null(&rval1);
|
||||
free_and_set_null(&rval2);
|
||||
|
||||
(void) set_errno(saved_errno, EINVAL);
|
||||
err_exit(errno, "dcat");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -433,6 +474,7 @@ err:
|
||||
int
|
||||
vcmp(const void *s1, const void *s2, size_t n)
|
||||
{
|
||||
int saved_errno = errno;
|
||||
size_t i = 0;
|
||||
size_t a;
|
||||
size_t b;
|
||||
@@ -459,6 +501,7 @@ vcmp(const void *s1, const void *s2, size_t n)
|
||||
if (x[i] != y[i])
|
||||
return (int)x[i] - (int)y[i];
|
||||
|
||||
errno = saved_errno;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user