Skip to content

Commit cf13259

Browse files
authored
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
1 parent b1cfb4b commit cf13259

File tree

2 files changed

+11
-11
lines changed

2 files changed

+11
-11
lines changed

server/src/main/java/org/elasticsearch/common/logging/ESLogMessage.java

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,11 @@
1818
*/
1919
package org.elasticsearch.common.logging;
2020

21-
import com.fasterxml.jackson.core.io.JsonStringEncoder;
2221
import org.apache.logging.log4j.message.MapMessage;
2322
import org.apache.logging.log4j.message.ParameterizedMessage;
2423
import org.apache.logging.log4j.util.Chars;
2524
import org.apache.logging.log4j.util.StringBuilders;
2625

27-
import java.nio.charset.Charset;
2826
import java.util.ArrayList;
2927
import java.util.Collections;
3028
import java.util.LinkedHashMap;
@@ -37,8 +35,6 @@
3735
* A base class for custom log4j logger messages. Carries additional fields which will populate JSON fields in logs.
3836
*/
3937
public class ESLogMessage extends MapMessage<ESLogMessage, Object> {
40-
private static final JsonStringEncoder JSON_STRING_ENCODER = JsonStringEncoder.getInstance();
41-
4238
private final String messagePattern;
4339
private final List<Object> arguments = new ArrayList<>();
4440

@@ -106,9 +102,4 @@ public static String asJsonArray(Stream<String> stream) {
106102
.map(ESLogMessage::inQuotes)
107103
.collect(Collectors.joining(", ")) + "]";
108104
}
109-
110-
public static String escapeJson(String text) {
111-
byte[] sourceEscaped = JSON_STRING_ENCODER.quoteAsUTF8(text);
112-
return new String(sourceEscaped, Charset.defaultCharset());
113-
}
114105
}

server/src/main/java/org/elasticsearch/index/SearchSlowLog.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
package org.elasticsearch.index;
2121

22+
import com.fasterxml.jackson.core.io.JsonStringEncoder;
2223
import org.apache.logging.log4j.LogManager;
2324
import org.apache.logging.log4j.Logger;
2425
import org.elasticsearch.common.Strings;
@@ -32,13 +33,16 @@
3233
import org.elasticsearch.search.internal.SearchContext;
3334
import org.elasticsearch.tasks.Task;
3435

36+
import java.nio.charset.Charset;
3537
import java.util.Collections;
3638
import java.util.HashMap;
3739
import java.util.Map;
3840
import java.util.concurrent.TimeUnit;
3941
import java.util.stream.Stream;
4042

4143
public final class SearchSlowLog implements SearchOperationListener {
44+
private static final Charset UTF_8 = Charset.forName("UTF-8");
45+
4246
private long queryWarnThreshold;
4347
private long queryInfoThreshold;
4448
private long queryDebugThreshold;
@@ -169,13 +173,13 @@ private static Map<String, Object> prepareMap(SearchContext context, long tookIn
169173
} else {
170174
messageFields.put("total_hits", "-1");
171175
}
172-
messageFields.put("stats", ESLogMessage.escapeJson(ESLogMessage.asJsonArray(
176+
messageFields.put("stats", escapeJson(ESLogMessage.asJsonArray(
173177
context.groupStats() != null ? context.groupStats().stream() : Stream.empty())));
174178
messageFields.put("search_type", context.searchType());
175179
messageFields.put("total_shards", context.numberOfShards());
176180

177181
if (context.request().source() != null) {
178-
String source = ESLogMessage.escapeJson(context.request().source().toString(FORMAT_PARAMS));
182+
String source = escapeJson(context.request().source().toString(FORMAT_PARAMS));
179183

180184
messageFields.put("source", source);
181185
} else {
@@ -221,6 +225,11 @@ private static String message(SearchContext context, long tookInNanos) {
221225
}
222226
return sb.toString();
223227
}
228+
229+
private static String escapeJson(String text) {
230+
byte[] sourceEscaped = JsonStringEncoder.getInstance().quoteAsUTF8(text);
231+
return new String(sourceEscaped, UTF_8);
232+
}
224233
}
225234

226235
private void setQueryWarnThreshold(TimeValue warnThreshold) {

0 commit comments

Comments
 (0)