Fix smaps parsing logic 59/116759/2 accepted/tizen_common accepted/tizen_ivi accepted/tizen_mobile accepted/tizen_tv accepted/tizen_wearable accepted/tizen/3.0/common/20170302.075821 accepted/tizen/3.0/ivi/20170302.034042 accepted/tizen/3.0/mobile/20170302.033941 accepted/tizen/3.0/tv/20170302.034004 accepted/tizen/3.0/wearable/20170302.034023 accepted/tizen/common/20170228.162222 accepted/tizen/ivi/20170302.120316 accepted/tizen/mobile/20170302.120235 accepted/tizen/tv/20170302.120244 accepted/tizen/unified/20170309.033717 accepted/tizen/wearable/20170302.120303 submit/tizen/20170228.110810 submit/tizen_3.0/20170228.114713 submit/tizen_unified/20170308.100409
authorHyeongsik Min <hyeongsik.min@samsung.com>
Tue, 28 Feb 2017 06:27:35 +0000 (15:27 +0900)
committerHyeongsik Min <hyeongsik.min@samsung.com>
Tue, 28 Feb 2017 08:45:37 +0000 (17:45 +0900)
Memps fails to parse smaps and gets crash when kernel shows anon name
information in /proc/smaps, because kernel adds additional line to
print the information.
Instead of using fixed smaps line count, this patch checks every line
to find VMA address line.

Change-Id: I5eaad65804f9cae67bfc62b6625b4b7da0eb27aa
Signed-off-by: Hyeongsik Min <hyeongsik.min@samsung.com>
memps.c

diff --git a/memps.c b/memps.c
index fd821b0..d944aa5 100644 (file)
--- a/memps.c
+++ b/memps.c
@@ -110,7 +110,6 @@ struct geminfo {
        unsigned hcount;
 };
 
-static int smaps_lcnt;
 static int sum;
 static int verbos;
 
@@ -319,17 +318,17 @@ static geminfo *load_geminfo(void)
  * 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  * 0         1         2         3         4         5         6         7
  */
-mapinfo *read_mapinfo(char** smaps, int line_cnt)
+mapinfo *read_mapinfo(char** smaps)
 {
        char* line;
        mapinfo *mi;
        int len;
        int n;
 
-       if ((--line_cnt <= 0) || (line = cgets(smaps)) == 0)
+       if ((line = cgets(smaps)) == 0)
                return 0;
 
-       len    = strlen(line);
+       len = strlen(line);
        if (len < 1)
                return 0;
 
@@ -342,8 +341,13 @@ mapinfo *read_mapinfo(char** smaps, int line_cnt)
 
        if (n == 3 && !mi->name)
                mi->name = strndup("[anon]", strlen("[anon]"));
+       else if (n <= 3) {
+               fprintf(stderr,"Fail to parse smaps\n");
+               free(mi);
+               return 0;
+       }
 
-       while (line_cnt-- && (line = cgets(smaps))) {
+       while ((line = cgets(smaps))) {
                if (sscanf(line, "Size: %d kB", &mi->size) == 1) {}
                else if (sscanf(line, "Rss: %d kB", &mi->rss) == 1) {}
                else if (sscanf(line, "Pss: %d kB", &mi->pss) == 1) {}
@@ -352,6 +356,12 @@ mapinfo *read_mapinfo(char** smaps, int line_cnt)
                else if (sscanf(line, "Private_Clean: %d kB", &mi->private_clean) == 1) {}
                else if (sscanf(line, "Private_Dirty: %d kB", &mi->private_dirty) == 1) {}
                else if (sscanf(line, "Swap: %d kB", &mi->swap) == 1) {}
+               if (*smaps) {
+                       /* Drain lines until it meets next VMA address */
+                       char next = **smaps;
+                       if  ((next >= '0' && next <= '9') || (next >= 'a' && next <= 'f'))
+                               break;
+               }
        }
 
        return mi;
@@ -657,7 +667,7 @@ mapinfo *load_maps(int pid)
        if (smaps == NULL)
                return 0;
 
-       while ((mi = read_mapinfo(&smaps, smaps_lcnt)) != 0) {
+       while ((mi = read_mapinfo(&smaps)) != 0) {
                if (milist) {
                        if ((!strcmp(mi->name, milist->name)
                             && (mi->name[0] != '['))) {
@@ -1186,109 +1196,12 @@ static int show_map_new(int pid)
        return 1;
 }
 
-int get_fixed_smaps_lcnt(void)
-{
-       struct utsname buf;
-       int ret;
-
-       ret = uname(&buf);
-
-       if (!ret) {
-               char *pch;
-               char str[3];
-               int sub_version;
-               pch = strstr(buf.release, ".");
-               strncpy(str, pch+1, 2);
-               sub_version = atoi(str);
-
-               if (buf.release[0] >= '4') {
-                       if (sub_version >= 4)
-                               ret = 19;
-                               /* Vma, Size, Rss, Pss, Shared_Clean, Shard_Dirty,
-                                * Private_Clean, Private_Drity,
-                                * Referenced, Anonymous, AnonHugePages, Shared_Hugetlb,
-                                * Private_Hugetlb, Swap, SwapPss, KernelPageSize,
-                                * MMUPageSize, Locked, VmFlags */
-                       else if (sub_version == 3)
-                               ret = 17;
-                               /* Vma, Size, Rss, Pss, Shared_Clean, Shard_Dirty,
-                                * Private_Clean, Private_Drity,
-                                * Referenced, Anonymous, AnonHugePages, Swap, SwapPss,
-                                * KernelPageSize, MMUPageSize, Locked, VmFlags */
-                       else
-                               ret = 16;
-                               /* Vma, Size, Rss, Pss, Shared_Clean, Shard_Dirty,
-                                * Private_Clean, Private_Drity,
-                                * Referenced, Anonymous, AnonHugePages, Swap,
-                                * KernelPageSize, MMUPageSize, Locked, VmFlags */
-               } else if (buf.release[0] == '3') {
-                       if (sub_version >= 10)
-                               ret = 16;
-                               /* Vma, Size, Rss, Pss, Shared_Clean, Shard_Dirty,
-                                * Private_Clean, Private_Drity,
-                                * Referenced, Anonymous, AnonHugePages, Swap,
-                                * KernelPageSize, MMUPageSize, Locked, VmFlags */
-                       else
-                               ret = 15;
-                               /* Vma, Size, Rss, Pss, Shared_Clean, Shard_Dirty,
-                                * Private_Clean, Private_Drity,
-                                * Referenced, Anonymous, AnonHugePages, Swap,
-                                * KernelPageSize, MMUPageSize, Locked */
-               } else {
-                       ret = 12;
-                               /* Vma, Size, Rss, Pss, Shared_Clean, Shard_Dirty,
-                                * Private_Clean, Private_Drity,
-                                * Referenced, Swap, KernelPageSize, MMUPageSize */
-               }
-       }
-       return ret;
-}
-
-int get_smaps_lcnt(void)
-{
-       char *buf, *buf_start, *line;
-       char cmd[64] = "/proc/self/smaps";
-       int line_count = 0;
-       long start_addr, end_addr;
-       unsigned long pg_off;
-       int major, minor;
-       char flags[4];
-
-       buf_start = cread(cmd);
-       if (buf_start == NULL) {
-               goto error;
-       }
-
-       buf = buf_start;
-       if ((line = cgets(&buf)) == 0)
-               goto error;
-
-       if (sscanf(line, "%lx-%lx %s %lx %x:%x",
-                       &start_addr, &end_addr, flags, &pg_off, &major, &minor) != 6) {
-               goto error;
-       }
-
-       while ((line = cgets(&buf)) != 0 ) {
-               line_count++;
-               if (sscanf(line, "%lx-%lx %s %lx %x:%x",
-                               &start_addr, &end_addr, flags, &pg_off, &major, &minor) == 6)
-                       break;
-       }
-
-       return line_count;
-
-error:
-       return get_fixed_smaps_lcnt();
-}
-
 int main(int argc, char *argv[])
 {
        int usage = 1;
        sum = 0;
 
        if (argc > 1) {
-               smaps_lcnt = get_smaps_lcnt();
-
                if (!strncmp(argv[1], "-r", strlen("-r")+1)) {
                        if (argc >= 3)
                                show_rss(OUTPUT_FILE, argv[2]);