Use %n to parse maps in libpagemap.

Bug: http://b/24212024
Change-Id: If00782c7af6fde30650045180512132ee5a8fd89
diff --git a/libpagemap/Android.mk b/libpagemap/Android.mk
index 96a4e94..05e6f01 100644
--- a/libpagemap/Android.mk
+++ b/libpagemap/Android.mk
@@ -13,17 +13,23 @@
 # limitations under the License.
 
 LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
 
+pagemap_src_files := \
+    pm_kernel.c \
+    pm_process.c \
+    pm_map.c \
+    pm_memusage.c \
+
+include $(CLEAR_VARS)
 LOCAL_MODULE := libpagemap
 LOCAL_MODULE_TAGS := debug
-
-LOCAL_SRC_FILES := \
-	pm_kernel.c \
-	pm_process.c \
-	pm_map.c \
-	pm_memusage.c
-
+LOCAL_SRC_FILES := $(pagemap_src_files)
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
 include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := pagemap_test
+LOCAL_SRC_FILES := pagemap_test.cpp
+LOCAL_SHARED_LIBRARIES := libpagemap
+include $(BUILD_NATIVE_TEST)
diff --git a/libpagemap/pagemap_test.cpp b/libpagemap/pagemap_test.cpp
new file mode 100644
index 0000000..ccbc211
--- /dev/null
+++ b/libpagemap/pagemap_test.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <pagemap/pagemap.h>
+
+TEST(pagemap, maps) {
+  pm_kernel_t* kernel;
+  ASSERT_EQ(0, pm_kernel_create(&kernel));
+
+  pm_process_t* process;
+  ASSERT_EQ(0, pm_process_create(kernel, getpid(), &process));
+
+  pm_map_t** maps;
+  size_t num_maps;
+  ASSERT_EQ(0, pm_process_maps(process, &maps, &num_maps));
+
+  bool found_heap = false;
+  bool found_stack = false;
+  for (size_t i = 0; i < num_maps; i++) {
+    if (strcmp(maps[i]->name, "[heap]") == 0) found_heap = true;
+    if (strcmp(maps[i]->name, "[stack]") == 0) found_stack = true;
+  }
+
+  ASSERT_TRUE(found_heap);
+  ASSERT_TRUE(found_stack);
+
+  free(maps);
+  pm_process_destroy(process);
+  pm_kernel_destroy(kernel);
+}
diff --git a/libpagemap/pm_process.c b/libpagemap/pm_process.c
index 4d56428..b8e06c1 100644
--- a/libpagemap/pm_process.c
+++ b/libpagemap/pm_process.c
@@ -231,19 +231,13 @@
 }
 
 #define INITIAL_MAPS 10
-#define MAX_LINE 1024
 #define MAX_PERMS 5
 
-/* 
- * #define FOO 123
- * S(FOO) => "123"
- */
-#define _S(n) #n
-#define S(n) _S(n)
-
 static int read_maps(pm_process_t *proc) {
     char filename[MAX_FILENAME];
-    char line[MAX_LINE], name[MAX_LINE], perms[MAX_PERMS];
+    char *line = NULL;
+    size_t line_length = 0;
+    char perms[MAX_PERMS];
     FILE *maps_f;
     pm_map_t *map, **maps, **new_maps;
     int maps_count, maps_size;
@@ -269,12 +263,15 @@
         return errno;
     }
 
-    while (fgets(line, MAX_LINE, maps_f)) {
+    while (getline(&line, &line_length, maps_f) != -1) {
+        line[strlen(line) - 1] = '\0'; // Lose the newline.
+
         if (maps_count >= maps_size) {
             new_maps = realloc(maps, 2 * maps_size * sizeof(pm_map_t*));
             if (!new_maps) {
                 error = errno;
                 free(maps);
+                free(line);
                 fclose(maps_f);
                 return error;
             }
@@ -286,20 +283,21 @@
 
         map->proc = proc;
 
-        name[0] = '\0';
-        sscanf(line, "%" SCNx64 "-%" SCNx64 " %s %" SCNx64 " %*s %*d %" S(MAX_LINE) "s",
-               &map->start, &map->end, perms, &map->offset, name);
+        int name_offset;
+        sscanf(line, "%" SCNx64 "-%" SCNx64 " %4s %" SCNx64 " %*s %*d %n",
+               &map->start, &map->end, perms, &map->offset, &name_offset);
 
-        map->name = malloc(strlen(name) + 1);
+        map->name = strdup(line + name_offset);
         if (!map->name) {
             error = errno;
             for (; maps_count > 0; maps_count--)
                 pm_map_destroy(maps[maps_count]);
             free(maps);
+            free(line);
             fclose(maps_f);
             return error;
         }
-        strcpy(map->name, name);
+
         if (perms[0] == 'r') map->flags |= PM_MAP_READ;
         if (perms[1] == 'w') map->flags |= PM_MAP_WRITE;
         if (perms[2] == 'x') map->flags |= PM_MAP_EXEC;
@@ -307,6 +305,7 @@
         maps_count++;
     }
 
+    free(line);
     fclose(maps_f);
 
     new_maps = realloc(maps, maps_count * sizeof(pm_map_t*));