aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric B Munson <emunson@mgebm.net>2012-12-01 13:43:59 -0500
committerEric B Munson <emunson@mgebm.net>2012-12-07 18:13:23 -0500
commit8c075e336029bad7d4fafd87cd1e47f75ab50073 (patch)
tree576cbd039b55d09011fa2a92f1e40c2857417b4e
parentbcfabcdfcf146df88f24c9ffe56d9c70628de54d (diff)
downloadlibhugetlbfs-8c075e336029bad7d4fafd87cd1e47f75ab50073.tar.gz
Remove use of sscanf in library setup
commit cdd2fa33 makes th library setup exhaust any heap allocated on small pages. This covers but does not address the cause of the allocation. As mentioned by Steve Capper, sscanf is the cause of the allocation. This patch removes the usage of sscanf from any function used in library setup prior to replacing _morecore. Signed-off-by: Eric B Munson <emunson@mgebm.net> Cc: Steve Capper <steve.capper@arm.com> Cc: Jan Stancek <jstancek@redhat.com>
-rw-r--r--hugeutils.c31
-rw-r--r--kernel-features.c64
2 files changed, 64 insertions, 31 deletions
diff --git a/hugeutils.c b/hugeutils.c
index f8e2b33..6a4dc85 100644
--- a/hugeutils.c
+++ b/hugeutils.c
@@ -623,7 +623,9 @@ static void find_mounts(void)
char path[PATH_MAX+1];
char line[LINE_MAXLEN + 1];
char *eol;
- int bytes, err, dummy;
+ char *match;
+ char *end;
+ int bytes;
off_t offset;
fd = open("/proc/mounts", O_RDONLY);
@@ -652,18 +654,21 @@ static void find_mounts(void)
offset = bytes - (eol + 1 - line);
lseek(fd, -offset, SEEK_CUR);
- /*
- * Match only hugetlbfs filesystems.
- * Subtle: sscanf returns the number of input items matched
- * and assigned. To force sscanf to match the literal
- * "hugetlbfs" string we include a 'dummy' input item
- * following that string.
- */
- err = sscanf(line, "%*s %" stringify(PATH_MAX) "s hugetlbfs "
- "%*s %d", path, &dummy);
- if ((err == 2) && (hugetlbfs_test_path(path) == 1) &&
- !(access(path, R_OK | W_OK | X_OK)))
- add_hugetlbfs_mount(path, 0);
+ /* Match only hugetlbfs filesystems. */
+ match = strstr(line, " hugetlbfs ");
+ if (match) {
+ match = strchr(line, '/');
+ if (!match)
+ continue;
+ end = strchr(match, ' ');
+ if (!end)
+ continue;
+
+ strncpy(path, match, end - match);
+ if ((hugetlbfs_test_path(path) == 1) &&
+ !(access(path, R_OK | W_OK | X_OK)))
+ add_hugetlbfs_mount(path, 0);
+ }
}
close(fd);
}
diff --git a/kernel-features.c b/kernel-features.c
index b8cdec9..e7639a4 100644
--- a/kernel-features.c
+++ b/kernel-features.c
@@ -67,39 +67,67 @@ static void debug_kernel_version(void)
static int str_to_ver(const char *str, struct kernel_version *ver)
{
- int err;
- int nr_chars;
- char extra[4];
+ char *start;
+ char *end;
/* Clear out version struct */
ver->major = ver->minor = ver->release = ver->post = ver->pre = 0;
- /* The kernel always starts x.y.z */
- err = sscanf(str, "%u.%u.%u%n", &ver->major, &ver->minor, &ver->release,
- &nr_chars);
/*
- * The sscanf man page says that %n may or may not affect the return
- * value so make sure it is at least 3 to cover the three kernel
- * version variables and assume nr_chars will be correctly assigned.
+ * The kernel always starts x.y.z
+ *
+ * Note: strtol is used in place of sscanf because when heap override is
+ * used this step happens before the _morecore replacement and sscanf
+ * does an internal heap allocation. This mean that the next allocation
+ * from the heap would be on small pages until the first block allocated
+ * by _morecore is exhausted
*/
- if (err < 3) {
+ errno = 0;
+ ver->major = strtol(str, &end, 10);
+ if (!ver->major && errno == EINVAL) {
ERROR("Unable to determine base kernel version: %s\n",
strerror(errno));
return -1;
}
- /* Advance the str by the number of characters indicated by sscanf */
- str += nr_chars;
+ start = end + 1;
+ errno = 0;
+ ver->minor = strtol(start, &end, 10);
+ if (!ver->minor && errno == EINVAL) {
+ ERROR("Unable to determine base kernel version: %s\n",
+ strerror(errno));
+ return -1;
+ }
+
+ start = end + 1;
+ errno = 0;
+ ver->release = strtol(start, &end, 10);
+ if (!ver->release && errno == EINVAL) {
+ ERROR("Unable to determine base kernel version: %s\n",
+ strerror(errno));
+ return -1;
+ }
/* Try to match a post/stable version */
- err = sscanf(str, ".%u", &ver->post);
- if (err == 1)
- return 0;
+ start = end + 1;
+ if (*end == '.') {
+ ver->post = strtol(start, &end, 10);
+ if (!ver->post && errno == EINVAL)
+ return 0;
+ }
/* Try to match a preN/rcN version */
- err = sscanf(str, "-%3[^0-9]%u", extra, &ver->pre);
- if (err != 2 || (strcmp(extra, "pre") != 0 && strcmp(extra, "rc") != 0))
- ver->pre = 0;
+ start = end + 1;
+ if (*end == '-') {
+ if (*start == 'r' && *(start + 1) == 'c')
+ start += 2;
+ else if (*start == 'p' &&
+ *(start + 1) == 'r' &&
+ *(start + 2) == 'e')
+ start += 3;
+
+ ver->pre = strtol(start, &end, 10);
+ }
/*
* For now we ignore any extraversions besides pre and post versions