aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/lib.h1
-rw-r--r--lib/xwrap.c21
2 files changed, 18 insertions, 4 deletions
diff --git a/lib/lib.h b/lib/lib.h
index 49b02bb5..07555396 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -81,6 +81,7 @@ void show_help(void);
// xwrap.c
void xstrncpy(char *dest, char *src, size_t size);
+void xstrncat(char *dest, char *src, size_t size);
void xexit(void) noreturn;
void *xmalloc(size_t size);
void *xzalloc(size_t size);
diff --git a/lib/xwrap.c b/lib/xwrap.c
index a2dd1c69..96db3522 100644
--- a/lib/xwrap.c
+++ b/lib/xwrap.c
@@ -9,13 +9,25 @@
#include "toys.h"
-// Strcpy with size checking: exit if there's not enough space for the string.
+// strcpy and strncat with size checking. Size is the total space in "dest",
+// including null terminator. Exit if there's not enough space for the string
+// (including space for the null terminator), because silently truncating is
+// still broken behavior. (And leaving the string unterminated is INSANE.)
void xstrncpy(char *dest, char *src, size_t size)
{
if (strlen(src)+1 > size) error_exit("'%s' > %ld bytes", src, (long)size);
strcpy(dest, src);
}
+void xstrncat(char *dest, char *src, size_t size)
+{
+ long len = strlen(src);
+
+ if (len+strlen(dest)+1 > size)
+ error_exit("'%s%s' > %ld bytes", src, (long)size);
+ strcpy(dest+len, src);
+}
+
void xexit(void)
{
if (toys.rebound) longjmp(*toys.rebound, 1);
@@ -52,9 +64,10 @@ void *xrealloc(void *ptr, size_t size)
// Die unless we can allocate a copy of this many bytes of string.
char *xstrndup(char *s, size_t n)
{
- char *ret = xmalloc(++n);
- strncpy(ret, s, n);
- ret[--n]=0;
+ char *ret = strndup(s, ++n);
+
+ if (!ret) error_exit("xstrndup");
+ ret[--n] = 0;
return ret;
}