summaryrefslogtreecommitdiff
path: root/libgcompat/string.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgcompat/string.c')
-rw-r--r--libgcompat/string.c249
1 files changed, 200 insertions, 49 deletions
diff --git a/libgcompat/string.c b/libgcompat/string.c
index 9045d5d..1d387a8 100644
--- a/libgcompat/string.c
+++ b/libgcompat/string.c
@@ -1,96 +1,247 @@
-#include <assert.h> /* assert */
-#include <string.h> /* memcpy, strcpy, strncat, strndup */
-#include <stdlib.h> /* strto[u?]ll */
+#define _GNU_SOURCE /* mempcpy */
+#include <assert.h> /* assert */
+#include <stddef.h> /* NULL, size_t */
+#include <stdint.h> /* SIZE_MAX */
+#include <string.h> /* memcpy, strcpy, strncat, strndup */
-/* "Checked" memcpy */
-void *__memcpy_chk(void *dest, const void *src, size_t len, size_t destlen)
+#include "alias.h" /* weak_alias */
+
+/**
+ * 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);
}
-/* "Checked" strcpy */
-char *__strcpy_chk(char *dest, const char *src, size_t destlen)
+/**
+ * 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(strlen(src) < destlen);
+ assert(destlen >= n);
+ if (dest < src) {
+ assert(dest + n <= src);
+ } else {
+ assert(src + n <= dest);
+ }
- return strcpy(dest, src);
+ return stpcpy(dest, src);
}
-/* Literally a useless __ alias. */
-char *__strndup(const char *str, size_t count)
+/**
+ * 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)
{
- return strndup(str, count);
+ 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);
}
-/* The existance of this method, and the fact it is used in real code, gives
- * me nightmares. */
-void *rawmemchr(const void *s, int c)
+/**
+ * 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)
{
- const unsigned char *haystack = s;
- unsigned char needle = (unsigned char)c;
- while(*haystack++ != needle);
- return (void *)haystack;
+ 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);
}
-extern __typeof(rawmemchr) __rawmemchr __attribute__((weak, alias("rawmemchr")));
+/**
+ * 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(destlen >= n);
+ if (dest < src) {
+ assert(dest + n <= src);
+ } else {
+ assert(src + n <= dest);
+ }
+
+ return strcpy(dest, src);
+}
+
+/**
+ * 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)
+{
+ 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);
+}
-/* Another useless __ alias */
-char *__strtok_r(char *str, const char *delim, char **saveptr)
+/**
+ * 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)
{
- return strtok_r(str, delim, saveptr);
+ 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);
}
-/* 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)
+/**
+ * Duplicate a specific number of bytes from a string.
+ */
+char *__strndup(const char *s, size_t size)
{
- return strsep(stringp, delim);
+ return strndup(s, size);
}
-/* Some day, when musl supports LC_NUMERIC, we can probably remove these */
-long long int strtoll_l(const char *nptr, char **endptr, int base, locale_t locale)
+/**
+ * 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 strtoll(nptr, endptr, base);
+ return strsep(stringp, delim);
}
-unsigned long long int strtoull_l(const char *nptr, char **endptr, int base, locale_t locale)
+/**
+ * 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 strtoull(nptr, endptr, base);
+ return strtok_r(s, delim, save_ptr);
}