diff --git a/include/log/log.h b/include/log/log.h index 6ad6f0a2e..e606a842f 100644 --- a/include/log/log.h +++ b/include/log/log.h @@ -589,6 +589,8 @@ int android_log_write_list_end(android_log_context ctx); int android_log_write_int32(android_log_context ctx, int32_t value); int android_log_write_int64(android_log_context ctx, int64_t value); int android_log_write_string8(android_log_context ctx, const char *value); +int android_log_write_string8_len(android_log_context ctx, + const char *value, size_t maxlen); int android_log_write_float32(android_log_context ctx, float value); /* Submit the composed list context to the specified logger id */ diff --git a/liblog/Android.mk b/liblog/Android.mk index c7b76d87a..dd5b518e7 100644 --- a/liblog/Android.mk +++ b/liblog/Android.mk @@ -24,11 +24,10 @@ include $(CLEAR_VARS) # so make sure we do not regret hard-coding it as follows: liblog_cflags := -DLIBLOG_LOG_TAG=1005 -liblog_host_sources := logd_write.c log_event_write.c fake_log_device.c event.logtags -liblog_target_sources := logd_write.c log_event_write.c event_tag_map.c log_time.cpp log_is_loggable.c -liblog_target_sources += logprint.c -liblog_target_sources += log_read.c -liblog_target_sources += log_event_list.c +liblog_sources := logd_write.c log_event_list.c log_event_write.c +liblog_host_sources := $(liblog_sources) fake_log_device.c event.logtags +liblog_target_sources := $(liblog_sources) event_tag_map.c +liblog_target_sources += log_time.cpp log_is_loggable.c logprint.c log_read.c # Shared and static library for host # ======================================================== diff --git a/liblog/log_event_list.c b/liblog/log_event_list.c index 50a27c090..2213f219c 100644 --- a/liblog/log_event_list.c +++ b/liblog/log_event_list.c @@ -195,9 +195,10 @@ int android_log_write_int64(android_log_context ctx, int64_t value) { return 0; } -int android_log_write_string8(android_log_context ctx, const char *value) { +int android_log_write_string8_len(android_log_context ctx, + const char *value, size_t maxlen) { size_t needed; - int32_t len; + ssize_t len; android_log_context_internal *context; context = (android_log_context_internal *)ctx; @@ -208,13 +209,13 @@ int android_log_write_string8(android_log_context ctx, const char *value) { return -EIO; } if (!value) { - return -EINVAL; + value = ""; } - len = strlen(value); - needed = sizeof(uint8_t) + sizeof(len) + len; + len = strnlen(value, maxlen); + needed = sizeof(uint8_t) + sizeof(int32_t) + len; if ((context->pos + needed) > MAX_EVENT_PAYLOAD) { /* Truncate string for delivery */ - len = MAX_EVENT_PAYLOAD - context->pos - 1 - sizeof(len); + len = MAX_EVENT_PAYLOAD - context->pos - 1 - sizeof(int32_t); if (len <= 0) { context->overflow = true; return -EIO; @@ -223,9 +224,15 @@ int android_log_write_string8(android_log_context ctx, const char *value) { context->count[context->list_nest_depth]++; context->storage[context->pos + 0] = EVENT_TYPE_STRING; copy4LE(&context->storage[context->pos + 1], len); - memcpy(&context->storage[context->pos + 5], value, len); + if (len) { + memcpy(&context->storage[context->pos + 5], value, len); + } context->pos += needed; - return 0; + return len; +} + +int android_log_write_string8(android_log_context ctx, const char *value) { + return android_log_write_string8_len(ctx, value, MAX_EVENT_PAYLOAD); } int android_log_write_float32(android_log_context ctx, float value) { diff --git a/liblog/log_event_write.c b/liblog/log_event_write.c index 0bc42d548..ad42edd30 100644 --- a/liblog/log_event_write.c +++ b/liblog/log_event_write.c @@ -15,74 +15,33 @@ */ #include -#include #include -#include -#define MAX_EVENT_PAYLOAD 512 #define MAX_SUBTAG_LEN 32 -static inline void copy4LE(uint8_t *buf, size_t pos, int val) +int __android_log_error_write(int tag, const char *subTag, int32_t uid, + const char *data, uint32_t dataLen) { - buf[pos] = val & 0xFF; - buf[pos+1] = (val >> 8) & 0xFF; - buf[pos+2] = (val >> 16) & 0xFF; - buf[pos+3] = (val >> 24) & 0xFF; -} + int ret = -EINVAL; -int __android_log_error_write(int tag, const char *subTag, int32_t uid, const char *data, - uint32_t dataLen) -{ - uint8_t buf[MAX_EVENT_PAYLOAD]; - size_t pos = 0; - uint32_t subTagLen = 0; - uint32_t roomLeftForData = 0; + if (subTag && (data || !dataLen)) { + android_log_context ctx = create_android_logger(tag); - if ((subTag == NULL) || ((data == NULL) && (dataLen != 0))) return -EINVAL; - - subTagLen = strlen(subTag); - - // Truncate subtags that are too long. - subTagLen = subTagLen > MAX_SUBTAG_LEN ? MAX_SUBTAG_LEN : subTagLen; - - // Truncate dataLen if it is too long. - roomLeftForData = MAX_EVENT_PAYLOAD - - (1 + // EVENT_TYPE_LIST - 1 + // Number of elements in list - 1 + // EVENT_TYPE_STRING - sizeof(subTagLen) + - subTagLen + - 1 + // EVENT_TYPE_INT - sizeof(uid) + - 1 + // EVENT_TYPE_STRING - sizeof(dataLen)); - dataLen = dataLen > roomLeftForData ? roomLeftForData : dataLen; - - buf[pos++] = EVENT_TYPE_LIST; - buf[pos++] = 3; // Number of elements in the list (subTag, uid, data) - - // Write sub tag. - buf[pos++] = EVENT_TYPE_STRING; - copy4LE(buf, pos, subTagLen); - pos += 4; - memcpy(&buf[pos], subTag, subTagLen); - pos += subTagLen; - - // Write UID. - buf[pos++] = EVENT_TYPE_INT; - copy4LE(buf, pos, uid); - pos += 4; - - // Write data. - buf[pos++] = EVENT_TYPE_STRING; - copy4LE(buf, pos, dataLen); - pos += 4; - if (dataLen != 0) - { - memcpy(&buf[pos], data, dataLen); - pos += dataLen; + ret = -ENOMEM; + if (ctx) { + ret = android_log_write_string8_len(ctx, subTag, MAX_SUBTAG_LEN); + if (ret >= 0) { + ret = android_log_write_int32(ctx, uid); + if (ret >= 0) { + ret = android_log_write_string8_len(ctx, data, dataLen); + if (ret >= 0) { + ret = android_log_write_list(ctx, LOG_ID_EVENTS); + } + } + } + android_log_destroy(&ctx); + } } - - return __android_log_bwrite(tag, buf, pos); + return ret; } diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp index 13178539d..50ecd2dff 100644 --- a/liblog/tests/liblog_test.cpp +++ b/liblog/tests/liblog_test.cpp @@ -1429,7 +1429,7 @@ TEST(liblog, android_errorWriteWithInfoLog__android_logger_list_read__data_too_l const int TAG = 123456782; const char SUBTAG[] = "test-subtag"; const int UID = -1; - const int DATA_LEN = SIZEOF_MAX_PAYLOAD_BUF; + const int DATA_LEN = sizeof(max_payload_buf); struct logger_list *logger_list; pid_t pid = getpid(); @@ -1500,9 +1500,9 @@ TEST(liblog, android_errorWriteWithInfoLog__android_logger_list_read__data_too_l } eventData += dataLen; - // 4 bytes for the tag, and 512 bytes for the log since the - // max_payload_buf should be truncated. - ASSERT_EQ(4 + 512, eventData - original); + // 4 bytes for the tag, and max_payload_buf should be truncated. + ASSERT_LE(4 + 512, eventData - original); // worst expectations + ASSERT_GT(4 + DATA_LEN, eventData - original); // must be truncated ++count; } @@ -2123,6 +2123,30 @@ static const char *event_test_7_level_suffix(uint32_t tag, size_t &expected_len) return "[1,[2,[3,[4,[5,[6]]]]]]"; } +static const char *event_test_android_log_error_write(uint32_t tag, size_t &expected_len) { + EXPECT_LE(0, __android_log_error_write(tag, "Hello World", 42, "dlroW olleH", 11)); + + expected_len = sizeof(uint32_t) + + sizeof(uint8_t) + sizeof(uint8_t) + + sizeof(uint8_t) + sizeof(uint32_t) + sizeof("Hello World") - 1 + + sizeof(uint8_t) + sizeof(uint32_t) + + sizeof(uint8_t) + sizeof(uint32_t) + sizeof("dlroW olleH") - 1; + + return "[Hello World,42,dlroW olleH]"; +} + +static const char *event_test_android_log_error_write_null(uint32_t tag, size_t &expected_len) { + EXPECT_LE(0, __android_log_error_write(tag, "Hello World", 42, NULL, 0)); + + expected_len = sizeof(uint32_t) + + sizeof(uint8_t) + sizeof(uint8_t) + + sizeof(uint8_t) + sizeof(uint32_t) + sizeof("Hello World") - 1 + + sizeof(uint8_t) + sizeof(uint32_t) + + sizeof(uint8_t) + sizeof(uint32_t) + sizeof("") - 1; + + return "[Hello World,42,]"; +} + // make sure all user buffers are flushed static void print_barrier() { std::cout.flush(); @@ -2241,6 +2265,14 @@ TEST(liblog, create_android_logger_7_level_suffix) { create_android_logger(event_test_7_level_suffix); } +TEST(liblog, create_android_logger_android_log_error_write) { + create_android_logger(event_test_android_log_error_write); +} + +TEST(liblog, create_android_logger_android_log_error_write_null) { + create_android_logger(event_test_android_log_error_write_null); +} + TEST(liblog, create_android_logger_overflow) { android_log_context ctx;