From c4a13537be7c81e29b9af0b99941c563334609d2 Mon Sep 17 00:00:00 2001 From: Jim Ferenczi Date: Wed, 23 Oct 2019 10:19:34 +0200 Subject: [PATCH] SearchSlowLog uses a non thread-safe object to escape json (#48363) This commit fixes the usage of JsonStringEncoder#quoteAsUTF8 in the SearchSlowLog. JsonStringEncoder#getInstance should always be called to get a thread local object but this assumption was broken by #44642. This means that any slow log can throw an AIOOBE since it uses the same byte array concurrently. Closes #48358 --- .../org/elasticsearch/common/logging/ESLogMessage.java | 8 -------- .../main/java/org/elasticsearch/index/SearchSlowLog.java | 9 +++++++++ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/common/logging/ESLogMessage.java b/server/src/main/java/org/elasticsearch/common/logging/ESLogMessage.java index 0d063f5a0d1c5..9044b00df729d 100644 --- a/server/src/main/java/org/elasticsearch/common/logging/ESLogMessage.java +++ b/server/src/main/java/org/elasticsearch/common/logging/ESLogMessage.java @@ -19,11 +19,9 @@ package org.elasticsearch.common.logging; -import com.fasterxml.jackson.core.io.JsonStringEncoder; import org.apache.logging.log4j.message.ParameterizedMessage; import org.elasticsearch.common.SuppressLoggerChecks; -import java.nio.charset.Charset; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -32,7 +30,6 @@ * A base class for custom log4j logger messages. Carries additional fields which will populate JSON fields in logs. */ public abstract class ESLogMessage extends ParameterizedMessage { - private static final JsonStringEncoder JSON_STRING_ENCODER = JsonStringEncoder.getInstance(); private final Map fields; /** @@ -45,11 +42,6 @@ public ESLogMessage(Map fields, String messagePattern, Object... this.fields = fields; } - public static String escapeJson(String text) { - byte[] sourceEscaped = JSON_STRING_ENCODER.quoteAsUTF8(text); - return new String(sourceEscaped, Charset.defaultCharset()); - } - public String getValueFor(String key) { Object value = fields.get(key); return value != null ? value.toString() : null; diff --git a/server/src/main/java/org/elasticsearch/index/SearchSlowLog.java b/server/src/main/java/org/elasticsearch/index/SearchSlowLog.java index b4d8419d07116..07225a177d1ea 100644 --- a/server/src/main/java/org/elasticsearch/index/SearchSlowLog.java +++ b/server/src/main/java/org/elasticsearch/index/SearchSlowLog.java @@ -19,6 +19,7 @@ package org.elasticsearch.index; +import com.fasterxml.jackson.core.io.JsonStringEncoder; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.elasticsearch.common.Strings; @@ -33,6 +34,7 @@ import org.elasticsearch.tasks.Task; import java.util.Arrays; +import java.nio.charset.Charset; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -40,6 +42,8 @@ import java.util.stream.Stream; public final class SearchSlowLog implements SearchOperationListener { + private static final Charset UTF_8 = Charset.forName("UTF-8"); + private long queryWarnThreshold; private long queryInfoThreshold; private long queryDebugThreshold; @@ -230,6 +234,11 @@ private static String message(SearchContext context, long tookInNanos) { } return sb.toString(); } + + private static String escapeJson(String text) { + byte[] sourceEscaped = JsonStringEncoder.getInstance().quoteAsUTF8(text); + return new String(sourceEscaped, UTF_8); + } } private void setQueryWarnThreshold(TimeValue warnThreshold) {