summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorRuss Allbery <rra@stanford.edu>2012-02-23 15:34:26 -0800
committerRuss Allbery <rra@stanford.edu>2012-02-23 15:34:26 -0800
commit3e1872e35b7ddaf4f568a94353bff79af7564e9a (patch)
tree247c464c8d0c48ecfbc5960483d2beebc3df9d07 /util
parentcfc54400f0e07bc3ca366eda56ad9f42c9239341 (diff)
Fix xstrndup to not allocate too much memory and add more tests
We weren't testing copying of short strings and strings without nul termination. Add additional tests for those. Change-Id: I990e7a40a69bf97d8b3e976645460c1fd29c984c
Diffstat (limited to 'util')
-rw-r--r--util/xmalloc.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/util/xmalloc.c b/util/xmalloc.c
index 839f5a0..a636941 100644
--- a/util/xmalloc.c
+++ b/util/xmalloc.c
@@ -165,19 +165,30 @@ x_strdup(const char *s, const char *file, int line)
}
+/*
+ * Avoid using the system strndup function since it may not exist (on Mac OS
+ * X, for example), and there's no need to introduce another portability
+ * requirement.
+ */
char *
x_strndup(const char *s, size_t size, const char *file, int line)
{
- char *p;
+ const char *p;
+ size_t length;
+ char *copy;
- p = malloc(size + 1);
- while (p == NULL) {
- (*xmalloc_error_handler)("strndup", size + 1, file, line);
- p = malloc(size + 1);
+ /* Don't assume that the source string is nul-terminated. */
+ for (p = s; (size_t) (p - s) < size && *p != '\0'; p++)
+ ;
+ length = p - s;
+ copy = malloc(length + 1);
+ while (copy == NULL) {
+ (*xmalloc_error_handler)("strndup", length + 1, file, line);
+ copy = malloc(length + 1);
}
- memcpy(p, s, size);
- p[size] = '\0';
- return p;
+ memcpy(copy, s, length);
+ copy[length] = '\0';
+ return copy;
}