Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/main/java/org/apache/xmlbeans/impl/schema/XsbReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@ SchemaAnnotation readAnnotation(SchemaContainer c) {
if (n == -1) {
return null;
}
checkAnnotationCount(n);
SchemaAnnotation.Attribute[] attributes =
new SchemaAnnotation.Attribute[n];
for (int i = 0; i < n; i++) {
Expand All @@ -397,13 +398,15 @@ SchemaAnnotation readAnnotation(SchemaContainer c) {

// Read documentation items
n = readInt();
checkAnnotationCount(n);
String[] docStrings = new String[n];
for (int i = 0; i < n; i++) {
docStrings[i] = readString();
}

// Read application info items
n = readInt();
checkAnnotationCount(n);
String[] appInfoStrings = new String[n];
for (int i = 0; i < n; i++) {
appInfoStrings[i] = readString();
Expand All @@ -422,6 +425,7 @@ void writeAnnotations(SchemaAnnotation[] anns) {

List<SchemaAnnotation> readAnnotations() {
int n = readInt();
checkAnnotationCount(n);
List<SchemaAnnotation> result = new ArrayList<>(n);
// BUGBUG(radup)
SchemaContainer container = typeSystem.getContainerNonNull("");
Expand All @@ -431,6 +435,13 @@ List<SchemaAnnotation> readAnnotations() {
return result;
}

private void checkAnnotationCount(int n) {
if (n < 0) {
throw new SchemaTypeLoaderException("Invalid annotation count " + n,
typeSystem.getName(), _handle, SchemaTypeLoaderException.UNRECOGNIZED_INDEX_ENTRY);
}
}

SchemaComponent.Ref readHandle() {
String handle = readString();
if (handle == null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.xmlbeans.impl.schema;

import org.apache.xmlbeans.SchemaTypeLoaderException;
import org.apache.xmlbeans.impl.util.LongUTFDataInputStream;
import org.junit.jupiter.api.Test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.lang.reflect.Field;

import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;

public class XsbReaderAnnotationCountTest {

// Builds a reader whose next reads come from the given on-wire ints, exactly
// as a crafted/corrupt .xsb annotation section would supply them. When
// withVersion is set the version fields are bumped so readAnnotation gets
// past its atLeast(2, 19, 0) guard and reaches the count reads.
private static XsbReader reader(boolean withVersion, int... ints) throws Exception {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
for (int i : ints) {
dos.writeInt(i); // same on-wire form as XsbReader.writeInt
}
dos.flush();

XsbReader reader = new XsbReader(new SchemaTypeSystemImpl("test"), "h");
set(reader, "_input", new LongUTFDataInputStream(new ByteArrayInputStream(bos.toByteArray())));
if (withVersion) {
set(reader, "_majorver", SchemaTypeSystemImpl.MAJOR_VERSION);
set(reader, "_minorver", SchemaTypeSystemImpl.MINOR_VERSION);
set(reader, "_releaseno", SchemaTypeSystemImpl.RELEASE_NUMBER);
}
return reader;
}

private static void set(XsbReader reader, String name, Object value) throws Exception {
Field f = XsbReader.class.getDeclaredField(name);
f.setAccessible(true);
f.set(reader, value);
}

@Test
void readAnnotationsRejectsNegativeCount() throws Exception {
XsbReader reader = reader(false, -2);
assertThrows(SchemaTypeLoaderException.class, reader::readAnnotations);
}

@Test
void readAnnotationRejectsNegativeAttributeCount() throws Exception {
XsbReader reader = reader(true, -2);
assertThrows(SchemaTypeLoaderException.class, () -> reader.readAnnotation(null));
}

@Test
void readAnnotationRejectsNegativeDocumentationCount() throws Exception {
XsbReader reader = reader(true, 0, -2);
assertThrows(SchemaTypeLoaderException.class, () -> reader.readAnnotation(null));
}

@Test
void readAnnotationRejectsNegativeAppinfoCount() throws Exception {
XsbReader reader = reader(true, 0, 0, -2);
assertThrows(SchemaTypeLoaderException.class, () -> reader.readAnnotation(null));
}

// -1 is the null-annotation sentinel and must still be accepted unchanged.
@Test
void readAnnotationKeepsNullSentinel() throws Exception {
XsbReader reader = reader(true, -1);
assertNull(reader.readAnnotation(null));
}
}