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 <emun...@mgebm.net> Cc: Steve Capper <steve.cap...@arm.com> Cc: Jan Stancek <jstan...@redhat.com> --- hugeutils.c | 31 +++++++++++++++----------- kernel-features.c | 64 ++++++++++++++++++++++++++++++++++++++--------------- 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 -- 1.7.10.4 ------------------------------------------------------------------------------ Keep yourself connected to Go Parallel: INSIGHTS What's next for parallel hardware, programming and related areas? Interviews and blogs by thought leaders keep you ahead of the curve. http://goparallel.sourceforge.net _______________________________________________ Libhugetlbfs-devel mailing list Libhugetlbfs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/libhugetlbfs-devel