rts: Fix parsing of profiler selectors
authorBen Gamari <bgamari.foss@gmail.com>
Thu, 7 Apr 2016 13:26:11 +0000 (15:26 +0200)
committerBen Gamari <ben@smart-cactus.org>
Thu, 7 Apr 2016 13:27:08 +0000 (15:27 +0200)
69822f0c5b67161b4d7558081bc94f6f3a7c5dbb broke this as it held on to a
reference into the `arg` string, which is later freed. Humbug.

Test Plan: Try using filtering

Reviewers: austin

Subscribers: thomie

Differential Revision: https://phabricator.haskell.org/D2090

GHC Trac Issues: #11810

rts/RtsFlags.c

index 3387355..7f0821a 100644 (file)
@@ -1566,7 +1566,7 @@ static rtsBool read_heap_profiling_flag(const char *arg_in)
     // However, for sanity we want to guarantee const-correctness and parsing
     // really ought to be an immutable operation. To avoid rewriting the parser
     // we just operate on a temporary copy of the argument.
-    char *arg = strdup(arg_in);
+    const char *arg = strdup(arg_in);
     rtsBool error = rtsFalse;
     switch (arg[2]) {
     case '\0':
@@ -1597,35 +1597,37 @@ static rtsBool read_heap_profiling_flag(const char *arg_in)
                 if (!right)
                     right = arg + strlen(arg);
 
-                *right = '\0';
+                char *selector = strndup(left, right - left);
 
                 switch (arg[2]) {
                 case 'c': // cost centre label select
-                    RtsFlags.ProfFlags.ccSelector = left;
+                    RtsFlags.ProfFlags.ccSelector = selector;
                     break;
                 case 'C':
-                    RtsFlags.ProfFlags.ccsSelector = left;
+                    RtsFlags.ProfFlags.ccsSelector = selector;
                     break;
                 case 'M':
                 case 'm': // cost centre module select
-                    RtsFlags.ProfFlags.modSelector = left;
+                    RtsFlags.ProfFlags.modSelector = selector;
                     break;
                 case 'D':
                 case 'd': // closure descr select
-                    RtsFlags.ProfFlags.descrSelector = left;
+                    RtsFlags.ProfFlags.descrSelector = selector;
                     break;
                 case 'Y':
                 case 'y': // closure type select
-                    RtsFlags.ProfFlags.typeSelector = left;
+                    RtsFlags.ProfFlags.typeSelector = selector;
                     break;
                 case 'R':
                 case 'r': // retainer select
-                    RtsFlags.ProfFlags.retainerSelector = left;
+                    RtsFlags.ProfFlags.retainerSelector = selector;
                     break;
                 case 'B':
                 case 'b': // biography select
-                    RtsFlags.ProfFlags.bioSelector = left;
+                    RtsFlags.ProfFlags.bioSelector = selector;
                     break;
+                default:
+                    free(selector);
                 }
             }
             break;