diff options
| author | Mark Salyzyn <salyzyn@google.com> | 2017-02-28 09:20:31 -0800 |
|---|---|---|
| committer | Mark Salyzyn <salyzyn@google.com> | 2017-03-01 08:48:33 -0800 |
| commit | b45a175cdc1fa00245ba13031b54d27074653f31 (patch) | |
| tree | 2cf1cb9c0d3175adc76559bff6626286d4d76251 /logcat | |
| parent | de022a841f61b8aae1abadb46755867da5e4f2df (diff) | |
| download | system_core-b45a175cdc1fa00245ba13031b54d27074653f31.tar.gz system_core-b45a175cdc1fa00245ba13031b54d27074653f31.tar.bz2 system_core-b45a175cdc1fa00245ba13031b54d27074653f31.zip | |
liblogcat: -v and ${ANDROID_PRINTF_LOG} support comma separated list
Deal with yet another reentrancy issue with strtok() and do not
treat optarg as fungible data, allocate a temporary copy. Add
support in the -v flag and environmental variable ANDROID_PRINTF_LOG
for a comma-separated list of format and format modifiers.
Test: manual + gTest logcat-unit-tests
Bug: 35326290
Change-Id: I073e5676d59ba41bfd36df86942342766ef730f1
Diffstat (limited to 'logcat')
| -rw-r--r-- | logcat/logcat.cpp | 59 |
1 files changed, 43 insertions, 16 deletions
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp index 3ce0db377..077332a64 100644 --- a/logcat/logcat.cpp +++ b/logcat/logcat.cpp @@ -446,6 +446,8 @@ static void show_help(android_logcat_context_internal* context) { " and individually flagged modifying adverbs can be added:\n" " color descriptive epoch monotonic printable uid\n" " usec UTC year zone\n" + " Multiple -v parameters or comma separated list of format and\n" + " format modifiers are allowed.\n" // private and undocumented nsec, no signal, too much noise // useful for -T or -t <timestamp> accurate testing though. " -D, --dividers Print dividers between each log buffer\n" @@ -726,7 +728,7 @@ void reportErrorName(const char** current, const char* name, static int __logcat(android_logcat_context_internal* context) { using namespace android; int err; - int hasSetLogFormat = 0; + bool hasSetLogFormat = false; bool clearLog = false; bool allSelected = false; bool getLogSize = false; @@ -849,6 +851,10 @@ static int __logcat(android_logcat_context_internal* context) { goto exit; } + // meant to catch comma-delimited values, but cast a wider + // net for stability dealing with possible mistaken inputs. + static const char delimiters[] = ",:; \t\n\r\f"; + // danger: getopt is _not_ reentrant optind = 1; for (;;) { @@ -1070,8 +1076,12 @@ static int __logcat(android_logcat_context_internal* context) { break; case 'b': { + std::unique_ptr<char, void (*)(void*)> buffers(strdup(optarg), + free); + optarg = buffers.get(); unsigned idMask = 0; - while (!!(optarg = strtok(optarg, ",:; \t\n\r\f"))) { + char* sv = nullptr; // protect against -ENOMEM above + while (!!(optarg = strtok_r(optarg, delimiters, &sv))) { if (!strcmp(optarg, "default")) { idMask |= (1 << LOG_ID_MAIN) | (1 << LOG_ID_SYSTEM) | (1 << LOG_ID_CRASH); @@ -1152,20 +1162,28 @@ static int __logcat(android_logcat_context_internal* context) { } break; - case 'v': + case 'v': { if (!strcmp(optarg, "help") || !strcmp(optarg, "--help")) { show_format_help(context); context->retval = EXIT_SUCCESS; goto exit; } - err = setLogFormat(context, optarg); - if (err < 0) { - logcat_panic(context, HELP_FORMAT, - "Invalid parameter \"%s\" to -v\n", optarg); - goto exit; + std::unique_ptr<char, void (*)(void*)> formats(strdup(optarg), + free); + optarg = formats.get(); + unsigned idMask = 0; + char* sv = nullptr; // protect against -ENOMEM above + while (!!(optarg = strtok_r(optarg, delimiters, &sv))) { + err = setLogFormat(context, optarg); + if (err < 0) { + logcat_panic(context, HELP_FORMAT, + "Invalid parameter \"%s\" to -v\n", optarg); + goto exit; + } + optarg = nullptr; + if (err) hasSetLogFormat = true; } - hasSetLogFormat |= err; - break; + } break; case 'Q': #define KERNEL_OPTION "androidboot.logcat=" @@ -1297,13 +1315,22 @@ static int __logcat(android_logcat_context_internal* context) { const char* logFormat = android::getenv(context, "ANDROID_PRINTF_LOG"); if (!!logFormat) { - err = setLogFormat(context, logFormat); - if ((err < 0) && context->error) { - fprintf(context->error, - "invalid format in ANDROID_PRINTF_LOG '%s'\n", - logFormat); + std::unique_ptr<char, void (*)(void*)> formats(strdup(logFormat), + free); + char* sv = nullptr; // protect against -ENOMEM above + char* arg = formats.get(); + while (!!(arg = strtok_r(arg, delimiters, &sv))) { + err = setLogFormat(context, arg); + // environment should not cause crash of logcat + if ((err < 0) && context->error) { + fprintf(context->error, + "invalid format in ANDROID_PRINTF_LOG '%s'\n", arg); + } + arg = nullptr; + if (err > 0) hasSetLogFormat = true; } - } else { + } + if (!hasSetLogFormat) { setLogFormat(context, "threadtime"); } } |
