[java] Resolve StackOverflow in JavaTypeDefinitionSimple.toString()

- Resolves #831
This commit is contained in:
Juan Martín Sotuyo Dodero
2018-01-08 11:22:12 -03:00
parent 0c9f27bbbe
commit 303f05d8d3
5 changed files with 81 additions and 4 deletions

View File

@ -158,4 +158,6 @@ public abstract class JavaTypeDefinition implements TypeDefinition {
public abstract JavaTypeDefinition getJavaType(int index);
public abstract int getJavaTypeCount();
protected abstract String shallowString();
}

View File

@ -21,8 +21,10 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
/* default */ class JavaTypeDefinitionSimple extends JavaTypeDefinition {
@ -243,7 +245,21 @@ import java.util.logging.Logger;
public String toString() {
return new StringBuilder("JavaTypeDefinition [clazz=").append(clazz)
.append(", definitionType=").append(getDefinitionType())
.append(", genericArgs=").append(genericArgs)
.append(", genericArgs=").append(genericArgs.stream().map(new Function<JavaTypeDefinition, String>() {
@Override
public String apply(final JavaTypeDefinition jtd) {
return jtd.shallowString();
}
}).collect(Collectors.toList()))
.append(", isGeneric=").append(isGeneric)
.append("]\n").toString();
}
@Override
public String shallowString() {
return new StringBuilder("JavaTypeDefinition [clazz=").append(clazz)
.append(", definitionType=").append(getDefinitionType())
.append(", isGeneric=").append(isGeneric)
.append("]\n").toString();
}

View File

@ -111,15 +111,20 @@ import java.util.Set;
public String toString() {
StringBuilder builder = new StringBuilder()
.append("JavaTypeDefinition ")
.append(getDefinitionType().toString())
.append(getDefinitionType())
.append(" [")
.append(typeList[0]);
for (int index = 1; index < typeList.length; ++index) {
builder.append(" && ");
builder.append(typeList[index]);
builder.append(" && ")
.append(typeList[index]);
}
return builder.append("]").toString();
}
@Override
protected String shallowString() {
return toString();
}
@Override
public boolean equals(Object obj) {

View File

@ -102,6 +102,7 @@ import net.sourceforge.pmd.typeresolution.testdata.MethodThirdPhase;
import net.sourceforge.pmd.typeresolution.testdata.NestedAnonymousClass;
import net.sourceforge.pmd.typeresolution.testdata.Operators;
import net.sourceforge.pmd.typeresolution.testdata.OverloadedMethodsUsage;
import net.sourceforge.pmd.typeresolution.testdata.PmdStackOverflow;
import net.sourceforge.pmd.typeresolution.testdata.Promotion;
import net.sourceforge.pmd.typeresolution.testdata.SubTypeUsage;
import net.sourceforge.pmd.typeresolution.testdata.SuperExpression;
@ -123,6 +124,12 @@ import net.sourceforge.pmd.typeresolution.testdata.dummytypes.SuperClassB2;
public class ClassTypeResolverTest {
@Test
public void stackOverflowTest() {
// See #831 https://github.com/pmd/pmd/issues/831 - [java] StackOverflow in JavaTypeDefinitionSimple.toString
parseAndTypeResolveForClass15(PmdStackOverflow.class);
}
@Test
public void testClassNameExists() {
ClassTypeResolver classTypeResolver = new ClassTypeResolver();

View File

@ -0,0 +1,47 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.typeresolution.testdata;
public class PmdStackOverflow {
public void shouldThrowStackOverfloError() {
MessageBuilder messageBuilder = new MessageBuilderA();
// Works
PartBuilder partBuilder = messageBuilder.newComponent();
messageBuilder.addComponent(partBuilder.withSomeValue("ABC"));
// Does not work
messageBuilder.addComponent(messageBuilder.newComponent().withSomeValue("ABC"));
}
}
abstract class MessageBuilder<T extends MessageBuilder, U extends PartBuilder<U>> {
public abstract U newComponent();
public T addComponent(U ignore) {
return (T) this;
}
}
class MessageBuilderA extends MessageBuilder<MessageBuilderA, PartBuilderA> {
@Override
public PartBuilderA newComponent() {
return new PartBuilderA();
}
}
class PartBuilder<T extends PartBuilder> {
public T withSomeValue(String ignore) {
return (T) this;
}
}
class PartBuilderA extends PartBuilder<PartBuilderA> {
}