summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Holland <samuel@sholland.org>2018-01-14 23:00:13 -0600
committerSamuel Holland <samuel@sholland.org>2018-01-15 00:02:54 -0600
commit48030f9988d803da367af5a3b888549851db2f58 (patch)
tree086a7cdfd390225d0f6a3846806fd0b29c466c33
parentf87541521e517e8b65a196eada58aceb098ca918 (diff)
downloadgcompat-48030f9988d803da367af5a3b888549851db2f58.tar.gz
gcompat-48030f9988d803da367af5a3b888549851db2f58.tar.bz2
gcompat-48030f9988d803da367af5a3b888549851db2f58.tar.xz
gcompat-48030f9988d803da367af5a3b888549851db2f58.zip
string: Clean up, fix bugs, implement LSB plus more
* Add all checked string functions from LSB, plus those found in use in other applications. Document those functions from LSB as such. * Use a consistent structure and paramater names for all functions. * Fix multiple off-by-one errors. * Use a less hacky and more optimized rawmemchr. * Sort functions by name. Signed-off-by: Samuel Holland <samuel@sholland.org>
-rw-r--r--libgcompat/string.c237
1 files changed, 199 insertions, 38 deletions
diff --git a/libgcompat/string.c b/libgcompat/string.c
index 2c05caf..1d387a8 100644
--- a/libgcompat/string.c
+++ b/libgcompat/string.c
@@ -1,86 +1,247 @@
+#define _GNU_SOURCE /* mempcpy */
#include <assert.h> /* assert */
-#include <stdlib.h> /* strto[u?]ll */
+#include <stddef.h> /* NULL, size_t */
+#include <stdint.h> /* SIZE_MAX */
#include <string.h> /* memcpy, strcpy, strncat, strndup */
#include "alias.h" /* weak_alias */
-/* "Checked" memcpy */
-void *__memcpy_chk(void *dest, const void *src, size_t len, size_t destlen)
+/**
+ * Copy bytes in memory, with buffer overflow checking.
+ *
+ * LSB 5.0: LSB-Core-generic/baselib---memcpy-chk-1.html
+ */
+void *__memcpy_chk(void *dest, const void *src, size_t n, size_t destlen)
{
assert(dest != NULL);
assert(src != NULL);
- assert(len <= destlen);
- if (src < dest) {
- assert(!(src + len >= dest));
+ assert(destlen >= n);
+ if (dest < src) {
+ assert((char *) dest + n <= (char *) src);
} else {
- assert(!(dest + len >= src));
+ assert((char *) src + n <= (char *) dest);
}
- return memcpy(dest, src, len);
+
+ return memcpy(dest, src, n);
}
-/* "Checked" strncat */
-char *__strncat_chk(char *dest, const char *src, size_t n, size_t destlen)
+/**
+ * Copy bytes in memory with overlapping areas, with buffer overflow checking.
+ *
+ * LSB 5.0: LSB-Core-generic/baselib---memmove-chk-1.html
+ */
+void *__memmove_chk(void *dest, const void *src, size_t n, size_t destlen)
{
assert(dest != NULL);
assert(src != NULL);
- assert(n <= destlen);
+ assert(destlen >= n);
- return strncat(dest, src, n);
+ return memmove(dest, src, n);
}
-/* "Checked" strcat */
-char *__strcat_chk(char *dest, const char *src, size_t destlen)
+/**
+ * Copy bytes in memory.
+ *
+ * LSB 5.0: LSB-Core-generic/baselib---mempcpy.html
+ */
+void *__mempcpy(void *dest, const void *src, size_t n)
{
- return strncat(dest, src, destlen - 1);
+ return mempcpy(dest, src, n);
}
-/* "Checked" strncpy */
-char *__strncpy_chk(char *dest, const char *src, size_t n, size_t destlen)
+/**
+ * Copy bytes in memory, with buffer overflow checking.
+ *
+ * LSB 5.0: LSB-Core-generic/baselib---mempcpy-chk-1.html
+ */
+void *__mempcpy_chk(void *dest, const void *src, size_t n, size_t destlen)
{
assert(dest != NULL);
assert(src != NULL);
- assert(strlen(src) < destlen);
+ assert(destlen >= n);
+ if (dest < src) {
+ assert((char *) dest + n <= (char *) src);
+ } else {
+ assert((char *) src + n <= (char *) dest);
+ }
- return strncpy(dest, src, n);
+ return mempcpy(dest, src, n);
+}
+
+/**
+ * Set bytes in memory, with buffer overflow checking.
+ *
+ * LSB 5.0: LSB-Core-generic/baselib---memset-chk-1.html
+ */
+void *__memset_chk(void *s, int c, size_t n, size_t buflen)
+{
+ assert(s != NULL);
+ assert(buflen >= n);
+
+ return memset(s, c, n);
+}
+
+/**
+ * Find byte in memory.
+ *
+ * LSB 5.0: LSB-Core-generic/baselib---rawmemchr.html
+ */
+void *__rawmemchr(const void *s, int c)
+{
+ return memchr(s, c, SIZE_MAX);
+}
+weak_alias(__rawmemchr, rawmemchr);
+
+/**
+ * Copy a string and return a pointer to the end of the result, with buffer
+ * overflow checking.
+ *
+ * LSB 5.0: LSB-Core-generic/baselib---stpcpy-chk-1.html
+ */
+char *__stpcpy_chk(char *dest, const char *src, size_t destlen)
+{
+ size_t n = strlen(src) + 1;
+
+ assert(dest != NULL);
+ assert(src != NULL);
+ assert(destlen >= n);
+ if (dest < src) {
+ assert(dest + n <= src);
+ } else {
+ assert(src + n <= dest);
+ }
+
+ return stpcpy(dest, src);
+}
+
+/**
+ * Copy a fixed-length string, returning a pointer to the array end, with buffer
+ * overflow checking.
+ *
+ * LSB 5.0: LSB-Core-generic/baselib---stpncpy-chk-1.html
+ */
+char *__stpncpy_chk(char *dest, const char *src, size_t n, size_t destlen)
+{
+ assert(dest != NULL);
+ assert(src != NULL);
+ assert(destlen >= n);
+ if (dest < src) {
+ assert(dest + n <= src);
+ } else {
+ assert(src + n <= dest);
+ }
+
+ return stpncpy(dest, src, n);
}
-/* "Checked" strcpy */
+/**
+ * Concatenate two strings, with buffer overflow checking.
+ *
+ * LSB 5.0: LSB-Core-generic/baselib---strcat-chk-1.html
+ */
+char *__strcat_chk(char *dest, const char *src, size_t destlen)
+{
+ size_t n = strlen(src) + 1;
+ size_t total = strnlen(dest, destlen) + n;
+
+ assert(dest != NULL);
+ assert(src != NULL);
+ assert(destlen >= total);
+ if (dest < src) {
+ assert(dest + total <= src);
+ } else {
+ assert(src + n <= dest);
+ }
+
+ return strcat(dest, src);
+}
+
+/**
+ * Copy a string, with buffer overflow checking.
+ *
+ * LSB 5.0: LSB-Core-generic/baselib---strcpy-chk-1.html
+ */
char *__strcpy_chk(char *dest, const char *src, size_t destlen)
{
+ size_t n = strlen(src) + 1;
+
assert(dest != NULL);
assert(src != NULL);
- assert(strlen(src) < destlen);
+ assert(destlen >= n);
+ if (dest < src) {
+ assert(dest + n <= src);
+ } else {
+ assert(src + n <= dest);
+ }
return strcpy(dest, src);
}
-/* Literally a useless __ alias. */
-char *__strndup(const char *str, size_t count)
+/**
+ * Concatenate a string with part of another, with buffer overflow checking.
+ *
+ * LSB 5.0: LSB-Core-generic/baselib---strncat-chk-1.html
+ */
+char *__strncat_chk(char *dest, const char *src, size_t n, size_t destlen)
{
- return strndup(str, count);
+ size_t total = strnlen(dest, destlen) + n + 1;
+
+ assert(dest != NULL);
+ assert(src != NULL);
+ assert(destlen >= total);
+ if (dest < src) {
+ assert(dest + total <= src);
+ } else {
+ assert(src + n <= dest);
+ }
+
+ return strncat(dest, src, n);
}
-/* The existance of this method, and the fact it is used in real code, gives
- * me nightmares. */
-void *__rawmemchr(const void *s, int c)
+/**
+ * Copy a fixed-length string, with buffer overflow checking.
+ *
+ * LSB 5.0: LSB-Core-generic/baselib---strncpy-chk-1.html
+ */
+char *__strncpy_chk(char *dest, const char *src, size_t n, size_t destlen)
{
- const unsigned char *haystack = s;
- unsigned char needle = (unsigned char) c;
- while (*haystack++ != needle)
- ;
- return (void *) haystack;
+ assert(dest != NULL);
+ assert(src != NULL);
+ assert(destlen >= n);
+ if (dest < src) {
+ assert(dest + n <= src);
+ } else {
+ assert(src + n <= dest);
+ }
+
+ return strncpy(dest, src, n);
}
-weak_alias(__rawmemchr, rawmemchr);
-/* Another useless __ alias */
-char *__strtok_r(char *str, const char *delim, char **saveptr)
+/**
+ * Duplicate a specific number of bytes from a string.
+ */
+char *__strndup(const char *s, size_t size)
{
- return strtok_r(str, delim, saveptr);
+ return strndup(s, size);
}
-/* The "global" definition of strsep in glibc, used when architecture dependent
- * assembler versions aren't good enough. */
+/**
+ * Extract token from string.
+ *
+ * The "global" definition of strsep in glibc, used when architecture dependent
+ * assembler versions aren't good enough.
+ */
char *__strsep_g(char **stringp, const char *delim)
{
return strsep(stringp, delim);
}
+
+/**
+ * Split string into tokens.
+ *
+ * LSB 5.0: LSB-Core-generic/baselib---strtok-r-1.html
+ */
+char *__strtok_r(char *s, const char *delim, char **save_ptr)
+{
+ return strtok_r(s, delim, save_ptr);
+}