Skip to content

Commit 288588d

Browse files
committed
fix LOGBACK-1628
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
1 parent 1f20887 commit 288588d

File tree

7 files changed

+52
-20
lines changed

7 files changed

+52
-20
lines changed

logback-classic/src/main/java/ch/qos/logback/classic/joran/JoranConfigurator.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
import ch.qos.logback.core.joran.spi.DefaultNestedComponentRegistry;
4646
import ch.qos.logback.core.joran.spi.ElementSelector;
4747
import ch.qos.logback.core.joran.spi.RuleStore;
48-
import ch.qos.logback.core.joran.util.ParentTag_Tag_Class_Tuple;
4948
import ch.qos.logback.core.model.AppenderModel;
5049
import ch.qos.logback.core.model.AppenderRefModel;
5150
import ch.qos.logback.core.model.DefineModel;
@@ -65,9 +64,7 @@
6564
import ch.qos.logback.core.model.processor.DefaultProcessor;
6665
import ch.qos.logback.core.model.processor.ModelInterpretationContext;
6766
import ch.qos.logback.core.model.processor.RefContainerDependencyAnalyser;
68-
import ch.qos.logback.core.model.util.TagUtil;
6967

70-
import java.util.List;
7168
/**
7269
* JoranConfigurator class adds rules specific to logback-classic.
7370
*
@@ -101,9 +98,6 @@ public void addInstanceRules(RuleStore rs) {
10198
// rs.addRule(new ElementSelector("*/if/else"), new ElseAction());
10299
// rs.addRule(new ElementSelector("*/if/else/*"), new NOPAction());
103100

104-
// add jmxConfigurator only if we have JMX available.
105-
// If running under JDK 1.4 (retrotranslateed logback) then we
106-
// might not have JMX.
107101
if (PlatformInfo.hasJMXObjectName()) {
108102
rs.addRule(new ElementSelector("configuration/jmxConfigurator"), new JMXConfiguratorAction());
109103
}

logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import ch.qos.logback.core.joran.spi.JoranException;
4545
import ch.qos.logback.core.pattern.parser.Parser;
4646
import ch.qos.logback.core.read.ListAppender;
47+
import ch.qos.logback.core.spi.ErrorCodes;
4748
import ch.qos.logback.core.spi.ScanException;
4849
import ch.qos.logback.core.status.Status;
4950
import ch.qos.logback.core.testUtil.RandomUtil;
@@ -87,7 +88,6 @@ public void simpleList() throws JoranException {
8788
@Test
8889
public void asyncWithMultipleAppendersInRoot() throws JoranException {
8990
configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "async/logback_1614.xml");
90-
StatusPrinter.print(loggerContext);
9191
Logger logger = loggerContext.getLogger(this.getClass().getName());
9292
Logger root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME);
9393
AsyncAppender asyncAppender = (AsyncAppender) root.getAppender("ASYNC");
@@ -104,7 +104,6 @@ public void asyncWithMultipleAppendersInRoot() throws JoranException {
104104
@Test
105105
public void simpleListWithImports() throws JoranException {
106106
configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "simpleListWithImports.xml");
107-
StatusPrinter.print(loggerContext);
108107
Logger logger = loggerContext.getLogger(this.getClass().getName());
109108
Logger root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME);
110109
ListAppender<ILoggingEvent> listAppender = (ListAppender<ILoggingEvent>) root.getAppender("LIST");
@@ -180,7 +179,6 @@ public void appenderRefSettingBySystemProperty() throws JoranException {
180179
@Test
181180
public void statusListener() throws JoranException {
182181
configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "statusListener.xml");
183-
StatusChecker checker = new StatusChecker(loggerContext);
184182
checker.assertIsErrorFree();
185183
checker.assertContainsMatch(Status.WARN,
186184
"Please use \"level\" attribute within <logger> or <root> elements instead.");
@@ -189,8 +187,7 @@ public void statusListener() throws JoranException {
189187
@Test
190188
public void statusListenerWithImports() throws JoranException {
191189
configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "statusListenerWithImports.xml");
192-
StatusPrinter.print(loggerContext);
193-
StatusChecker checker = new StatusChecker(loggerContext);
190+
//StatusPrinter.print(loggerContext);
194191
checker.assertIsErrorFree();
195192
checker.assertContainsMatch(Status.WARN,
196193
"Please use \"level\" attribute within <logger> or <root> elements instead.");
@@ -397,7 +394,6 @@ public void encoderCharset() throws JoranException, IOException, InterruptedExce
397394

398395
assertEquals("UTF-8", encoder.getCharset().displayName());
399396

400-
StatusChecker checker = new StatusChecker(loggerContext);
401397
checker.assertIsErrorFree();
402398
}
403399

@@ -419,7 +415,6 @@ public void levelChangePropagator0() throws JoranException, IOException, Interru
419415
java.util.logging.Logger.getLogger(loggerName).setLevel(java.util.logging.Level.INFO);
420416
String configFileAsStr = ClassicTestConstants.JORAN_INPUT_PREFIX + "/jul/levelChangePropagator0.xml";
421417
configure(configFileAsStr);
422-
StatusChecker checker = new StatusChecker(loggerContext);
423418

424419
checker.assertIsErrorFree();
425420
verifyJULLevel(loggerName, null);
@@ -435,7 +430,7 @@ public void levelChangePropagator1() throws JoranException, IOException, Interru
435430
verifyJULLevel(loggerName, Level.INFO);
436431
String configFileAsStr = ClassicTestConstants.JORAN_INPUT_PREFIX + "/jul/levelChangePropagator1.xml";
437432
configure(configFileAsStr);
438-
StatusChecker checker = new StatusChecker(loggerContext);
433+
439434
checker.assertIsErrorFree();
440435
verifyJULLevel(loggerName, Level.INFO); //
441436
verifyJULLevel("a.b.c." + diff, Level.WARN);
@@ -569,7 +564,6 @@ public void unreferencedAppendersShouldBeSkipped() throws JoranException {
569564

570565
final ListAppender<ILoggingEvent> listAppenderA = (ListAppender<ILoggingEvent>) root.getAppender("A");
571566
assertNotNull(listAppenderA);
572-
StatusChecker checker = new StatusChecker(loggerContext);
573567
checker.assertContainsMatch(Status.WARN, "Appender named \\[B\\] not referenced. Skipping further processing.");
574568
}
575569

@@ -628,7 +622,18 @@ public void kvp() throws JoranException {
628622
assertTrue(slAppender.strList.get(2).contains("null=\"" + kvpNullKey.value + "\" " + msg));
629623
assertTrue(slAppender.strList.get(3).contains(kvpNullValue.key + "=\"null\" " + msg));
630624
}
631-
625+
626+
627+
// https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=46697
628+
@Test
629+
public void ossFuzz_46697() throws JoranException {
630+
System.out.println("==========");
631+
configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "ossfuzz/fuzz-46697.xml");
632+
633+
checker.assertContainsMatch(Status.ERROR, ErrorCodes.EMPTY_MODEL_STACK);
634+
StatusPrinter.print(loggerContext);
635+
}
636+
632637
// @Test
633638
// public void doTest() throws JoranException {
634639
// int LIMIT = 0;

logback-core/src/main/java/ch/qos/logback/core/joran/GenericXMLConfigurator.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import ch.qos.logback.core.model.processor.DefaultProcessor;
4141
import ch.qos.logback.core.model.processor.ModelInterpretationContext;
4242
import ch.qos.logback.core.spi.ContextAwareBase;
43+
import ch.qos.logback.core.spi.ErrorCodes;
4344
import ch.qos.logback.core.status.StatusUtil;
4445

4546
public abstract class GenericXMLConfigurator extends ContextAwareBase {
@@ -157,6 +158,10 @@ public final void doConfigure(final InputSource inputSource) throws JoranExcepti
157158

158159
SaxEventRecorder recorder = populateSaxEventRecorder(inputSource);
159160
Model top = buildModelFromSaxEventList(recorder.saxEventList);
161+
if(top == null) {
162+
addError(ErrorCodes.EMPTY_MODEL_STACK);
163+
return;
164+
}
160165
processModel(top);
161166

162167
// no exceptions a this level

logback-core/src/main/java/ch/qos/logback/core/joran/action/ImplicitModelAction.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
/**
2+
* Logback: the reliable, generic, fast and flexible logging framework.
3+
* Copyright (C) 1999-2022, QOS.ch. All rights reserved.
4+
*
5+
* This program and the accompanying materials are dual-licensed under
6+
* either the terms of the Eclipse Public License v1.0 as published by
7+
* the Eclipse Foundation
8+
*
9+
* or (per the licensee's choosing)
10+
*
11+
* under the terms of the GNU Lesser General Public License version 2.1
12+
* as published by the Free Software Foundation.
13+
*/
114
package ch.qos.logback.core.joran.action;
215

316
import java.util.Stack;
@@ -8,6 +21,7 @@
821
import ch.qos.logback.core.joran.spi.SaxEventInterpretationContext;
922
import ch.qos.logback.core.model.ImplicitModel;
1023
import ch.qos.logback.core.model.Model;
24+
import ch.qos.logback.core.spi.ErrorCodes;
1125

1226
/**
1327
*
@@ -58,7 +72,12 @@ public void end(SaxEventInterpretationContext interpretationContext, String name
5872
return;
5973
}
6074
Model parentModel = interpretationContext.peekModel();
61-
parentModel.addSubModel(implicitModel);
75+
if(parentModel != null) {
76+
parentModel.addSubModel(implicitModel);
77+
} else {
78+
addWarn(ErrorCodes.PARENT_MODEL_NOT_FOUND);
79+
addWarn(ErrorCodes.SKIPPING_IMCICIT_MODEL_ADDITION);
80+
}
6281
currentImplicitModelStack.pop();
6382

6483
}

logback-core/src/main/java/ch/qos/logback/core/joran/action/IncludeAction.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public void begin(SaxEventInterpretationContext ec, String name, Attributes attr
6565

6666
String optionalStr = attributes.getValue(OPTIONAL_ATTR);
6767

68-
createModelForNonXMLUse(ec, name, attributes, optionalStr);
68+
createModelForAlternateUse(ec, name, attributes, optionalStr);
6969

7070

7171
this.attributeInUse = null;
@@ -97,7 +97,8 @@ public void begin(SaxEventInterpretationContext ec, String name, Attributes attr
9797

9898
}
9999

100-
private void createModelForNonXMLUse(SaxEventInterpretationContext seic, String name, Attributes attributes,
100+
// model created for later use, not necessarily for configuration purposes.
101+
private void createModelForAlternateUse(SaxEventInterpretationContext seic, String name, Attributes attributes,
101102
String optionalStr) {
102103
this.includeModel = new IncludeModel();
103104
this.includeModel.setOptional(optionalStr);

logback-core/src/main/java/ch/qos/logback/core/joran/spi/SaxEventInterpretationContext.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,15 @@ public SaxEventInterpreter getSaxEventInterpreter() {
158158
// return implicitActionDataStack;
159159
// }
160160
//
161+
/**
162+
* Return the Model at the top of the model stack, may return null.
163+
*
164+
* @return
165+
*/
161166
public Model peekModel() {
167+
if(modelStack.isEmpty()) {
168+
return null;
169+
}
162170
return modelStack.peek();
163171
}
164172

logback-core/src/main/java/ch/qos/logback/core/spi/ErrorCodes.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* Logback: the reliable, generic, fast and flexible logging framework.
3-
* Copyright (C) 1999-2015, QOS.ch. All rights reserved.
3+
* Copyright (C) 1999-2022, QOS.ch. All rights reserved.
44
*
55
* This program and the accompanying materials are dual-licensed under
66
* either the terms of the Eclipse Public License v1.0 as published by

0 commit comments

Comments
 (0)