Skip to content

Commit

Permalink
#135 Fix UOE when using Custom Fields (#136)
Browse files Browse the repository at this point in the history
Log4j can provide different context data depending on its configuration.
In one case the provided context map is unmodifiable. In that case an
exception occurred, when a custom field was used as a message parameter.
This change guards against that issue, by defensively creating a modifiable
map of properties. Then the custom fields can be added safely.
  • Loading branch information
KarstenSchnitter authored Jan 24, 2022
1 parent a387108 commit 16e8e3c
Showing 1 changed file with 26 additions and 17 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.sap.hcp.cf.log4j2.converter;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import org.apache.logging.log4j.core.LogEvent;
Expand Down Expand Up @@ -47,30 +48,38 @@ public static ContextPropsConverter newInstance(final String[] options) {

@Override
public void format(LogEvent event, StringBuilder toAppendTo) {
Map<String, String> contextData = event.getContextData().toMap();
addCustomFieldsFromArguments(contextData, event);
Map<String, String> contextData = event.getContextData().toMap();
contextData = addCustomFieldsFromArguments(contextData, event);
int lengthBefore = toAppendTo.length();
converter.convert(toAppendTo, contextData);
converter.convert(toAppendTo, contextData);
// remove comma from pattern, when no properties are added
// this is to avoid a double comma in the JSON
// Do not do this on empty messages
if (toAppendTo.length() == lengthBefore && lengthBefore > 0 && toAppendTo.charAt(lengthBefore - 1) == ',') {
toAppendTo.setLength(lengthBefore - 1);
}
}
}

private void addCustomFieldsFromArguments(Map<String, String> contextData, LogEvent event) {
Message message = event.getMessage();
Object[] parameters = message.getParameters();
if (parameters == null) {
return;
}
for (Object current : parameters) {
if (current instanceof CustomField) {
CustomField field = (CustomField) current;
contextData.put(field.getKey(), field.getValue());
}
}
}
private Map<String, String> addCustomFieldsFromArguments(Map<String, String> contextData, LogEvent event) {
Message message = event.getMessage();
Object[] parameters = message.getParameters();
if (parameters == null) {
return contextData;
}
boolean unchangedContextData = true;
Map<String, String> result = contextData;
for (Object current: parameters) {
if (current instanceof CustomField) {
CustomField field = (CustomField) current;
if (unchangedContextData) {
// contextData might be an unmodifiable map
result = new HashMap<>(contextData);
unchangedContextData = false;
}
result.put(field.getKey(), field.getValue());
}
}
return result;
}

}

0 comments on commit 16e8e3c

Please sign in to comment.