Skip to content

Commit 03a1903

Browse files
committed
fix stack overflow issue with recursive schema
Currently, if you add a self-referencing type to multiple APIs, a StackOverflowError will occur. This change fixes that by not attempting to add a type to an API that's already added.
1 parent 0caa0d4 commit 03a1903

File tree

2 files changed

+28
-0
lines changed

2 files changed

+28
-0
lines changed

endpoints-framework/src/main/java/com/google/api/server/spi/config/model/SchemaRepository.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,9 @@ private Schema getOrCreateTypeForConfig(
170170
}
171171

172172
private void addSchemaToApi(ApiKey key, Schema schema) {
173+
if (schemaByApiKeys.containsEntry(key, schema)) {
174+
return;
175+
}
173176
schemaByApiKeys.put(key, schema);
174177
for (Field f : schema.fields().values()) {
175178
while (f.type() == FieldType.ARRAY) {

endpoints-framework/src/test/java/com/google/api/server/spi/config/model/SchemaRepositoryTest.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,25 @@ public void getOrAdd_enum() throws Exception {
114114
.build());
115115
}
116116

117+
@Test
118+
public void getOrAdd_recursiveSchema() throws Exception {
119+
TypeToken<SelfReferencingObject> type = TypeToken.of(SelfReferencingObject.class);
120+
// This test checks the case where a schema is added multiple times. The second time it's added
121+
// to an API, it recurses through the schema. If the schema is self-referencing, we must not
122+
// stack overflow.
123+
repo.getOrAdd(type, config);
124+
assertThat(repo.getOrAdd(type, config))
125+
.isEqualTo(Schema.builder()
126+
.setName("SelfReferencingObject")
127+
.setType("object")
128+
.addField("foo", Field.builder()
129+
.setName("foo")
130+
.setType(FieldType.OBJECT)
131+
.setSchemaReference(SchemaReference.create(repo, config, type))
132+
.build())
133+
.build());
134+
}
135+
117136
@Test
118137
public void get() {
119138
TypeToken<Parameterized<Integer>> type = new TypeToken<Parameterized<Integer>>() {};
@@ -204,6 +223,12 @@ public Parameterized<Short> transformFrom(Parameterized<String> in) {
204223
}
205224
}
206225

226+
private static class SelfReferencingObject {
227+
public SelfReferencingObject getFoo() {
228+
return null;
229+
}
230+
}
231+
207232
private ApiMethodConfig fooEndpointSetParameterized() throws Exception {
208233
return getMethodConfig("setParameterized", Parameterized.class);
209234
}

0 commit comments

Comments
 (0)