diff --git a/.github/workflows/test-lang-py.yml b/.github/workflows/test-lang-py.yml
index 00485b7103e..08e319a99fe 100644
--- a/.github/workflows/test-lang-py.yml
+++ b/.github/workflows/test-lang-py.yml
@@ -44,10 +44,7 @@ jobs:
- '3.10'
- '3.9'
- '3.8'
- - '3.7'
- - '3.6'
- - 'pypy-3.7'
- - 'pypy-3.6'
+ - 'pypy-3.10'
steps:
- uses: actions/checkout@v4
@@ -91,10 +88,17 @@ jobs:
- '3.10'
- '3.9'
- '3.8'
+<<<<<<< HEAD
- '3.7'
+<<<<<<< HEAD
- '3.6'
- 'pypy-3.7'
- 'pypy-3.6'
+=======
+=======
+>>>>>>> 6e5e37876b (Drop apparently unsupported pypy version)
+ - 'pypy-3.10'
+>>>>>>> 982ad792ce (ci: Remove deprecated pypy-3.9 test (#3211))
steps:
- uses: actions/checkout@v4
diff --git a/build.sh b/build.sh
index a6327b28d5c..d30c6b142c7 100755
--- a/build.sh
+++ b/build.sh
@@ -182,7 +182,8 @@ do
# build docs
cp -r doc/ build/staging-web/
find build/staging-web/ -type f -print0 | xargs -0 sed -r -i "s#\+\+version\+\+#${VERSION,,}#g"
- mv build/staging-web/content/en/docs/++version++ build/staging-web/content/en/docs/"${VERSION,,}"
+ mkdir -p build/staging-web/public/docs/
+ mv build/staging-web/content/en/docs/++version++ build/staging-web/public/docs/"${VERSION,,}"
read -n 1 -s -r -p "Build build/staging-web/ manually now. Press a key to continue..."
# If it was a SNAPSHOT, it was lowercased during the build.
cp -R build/staging-web/public/docs/"${VERSION,,}"/* "build/$DOC_DIR/"
@@ -217,7 +218,6 @@ do
else
gpg --pinentry-mode loopback --local-user="$GPG_LOCAL_USER" --passphrase "$password" --armor --output "$f.asc" --detach-sig "$f"
fi
-
done
set -x
diff --git a/doc/examples/java-example/pom.xml b/doc/examples/java-example/pom.xml
index a71aab28c09..6fc2cfffc0e 100644
--- a/doc/examples/java-example/pom.xml
+++ b/doc/examples/java-example/pom.xml
@@ -38,7 +38,7 @@
org.apache.avro
avro
- 1.11.4
+ 1.11.5
@@ -55,7 +55,7 @@
org.apache.avro
avro-maven-plugin
- 1.11.4
+ 1.11.5
generate-sources
@@ -72,7 +72,7 @@
org.apache.maven.plugins
maven-plugin
- 1.11.4
+ 1.11.5
1.8
1.8
@@ -92,7 +92,7 @@
org.apache.avro
avro-maven-plugin
- [1.11.4,)
+ [1.11.5,)
schema
diff --git a/doc/examples/mr-example/pom.xml b/doc/examples/mr-example/pom.xml
index aae8c723c1e..66fa36f2499 100644
--- a/doc/examples/mr-example/pom.xml
+++ b/doc/examples/mr-example/pom.xml
@@ -45,7 +45,7 @@
org.apache.avro
avro-maven-plugin
- 1.11.4
+ 1.11.5
generate-sources
@@ -73,7 +73,7 @@
org.apache.avro
avro-maven-plugin
- [1.11.4,)
+ [1.11.5,)
schema
@@ -94,12 +94,12 @@
org.apache.avro
avro
- 1.11.4
+ 1.11.5
org.apache.avro
avro-mapred
- 1.11.4
+ 1.11.5
org.apache.hadoop
diff --git a/lang/java/android/pom.xml b/lang/java/android/pom.xml
index 46904c52af6..49ff1832a1c 100644
--- a/lang/java/android/pom.xml
+++ b/lang/java/android/pom.xml
@@ -22,7 +22,7 @@
avro-parent
org.apache.avro
- 1.11.4
+ 1.11.5
../pom.xml
diff --git a/lang/java/archetypes/avro-service-archetype/pom.xml b/lang/java/archetypes/avro-service-archetype/pom.xml
index d293b0936fe..4204aad6b95 100644
--- a/lang/java/archetypes/avro-service-archetype/pom.xml
+++ b/lang/java/archetypes/avro-service-archetype/pom.xml
@@ -23,7 +23,7 @@
avro-archetypes-parent
org.apache.avro
- 1.11.4
+ 1.11.5
../pom.xml
diff --git a/lang/java/archetypes/pom.xml b/lang/java/archetypes/pom.xml
index a632ae7b5d5..aff41d24305 100644
--- a/lang/java/archetypes/pom.xml
+++ b/lang/java/archetypes/pom.xml
@@ -22,7 +22,7 @@
org.apache.avro
avro-parent
- 1.11.4
+ 1.11.5
../pom.xml
diff --git a/lang/java/avro/pom.xml b/lang/java/avro/pom.xml
index 7064f080f7f..3ef5d02ea8c 100644
--- a/lang/java/avro/pom.xml
+++ b/lang/java/avro/pom.xml
@@ -23,7 +23,7 @@
avro-parent
org.apache.avro
- 1.11.4
+ 1.11.5
../
@@ -72,6 +72,9 @@
maven-surefire-plugin
none
+
+ java.math.BigDecimal,java.math.BigInteger,java.net.URI,java.net.URL,java.io.File,java.lang.Integer,org.apache.avro.reflect.TestReflect$R10
+
diff --git a/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificDatumReader.java b/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificDatumReader.java
index 8950f165991..510c9fed84d 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificDatumReader.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificDatumReader.java
@@ -23,10 +23,14 @@
import org.apache.avro.generic.GenericDatumReader;
import org.apache.avro.io.ResolvingDecoder;
import org.apache.avro.util.ClassUtils;
+
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Stream;
/**
* {@link org.apache.avro.io.DatumReader DatumReader} for generated Java
@@ -34,14 +38,48 @@
*/
public class SpecificDatumReader extends GenericDatumReader {
+ /**
+ * @deprecated prefer to use {@link #SERIALIZABLE_CLASSES} instead.
+ */
+ @Deprecated
public static final String[] SERIALIZABLE_PACKAGES;
+ public static final String[] SERIALIZABLE_CLASSES;
+
static {
- SERIALIZABLE_PACKAGES = System.getProperty("org.apache.avro.SERIALIZABLE_PACKAGES",
- "java.lang,java.math,java.io,java.net,org.apache.avro.reflect").split(",");
+ // no serializable classes by default
+ SERIALIZABLE_CLASSES = streamPropertyEntries(System.getProperty("org.apache.avro.SERIALIZABLE_CLASSES"))
+ .toArray(String[]::new);
+
+ // no serializable packages by default
+ SERIALIZABLE_PACKAGES = streamPropertyEntries(System.getProperty("org.apache.avro.SERIALIZABLE_PACKAGES"))
+ // Add a '.' suffix to ensure we'll be matching package names instead of
+ // arbitrary prefixes, except for the wildcard "*", which allows all
+ // packages (this is only safe in fully controlled environments!).
+ .map(entry -> "*".equals(entry) ? entry : entry + ".").toArray(String[]::new);
+ }
+
+ /**
+ * Parse a comma separated list into non-empty entries. Leading and trailing
+ * whitespace is stripped.
+ *
+ * @param commaSeparatedEntries the comma separated list of entries
+ * @return a stream of the entries
+ */
+ private static Stream streamPropertyEntries(String commaSeparatedEntries) {
+ if (commaSeparatedEntries == null) {
+ return Stream.empty();
+ }
+ return Stream.of(commaSeparatedEntries.split(",")).map(String::trim).filter(s -> !s.isEmpty());
}
+ // The primitive "class names" based on Class.isPrimitive()
+ private static final Set PRIMITIVES = new HashSet<>(Arrays.asList(Boolean.TYPE.getName(),
+ Character.TYPE.getName(), Byte.TYPE.getName(), Short.TYPE.getName(), Integer.TYPE.getName(), Long.TYPE.getName(),
+ Float.TYPE.getName(), Double.TYPE.getName(), Void.TYPE.getName()));
+
private final List trustedPackages = new ArrayList<>();
+ private final List trustedClasses = new ArrayList<>();
public SpecificDatumReader() {
this(null, null, SpecificData.get());
@@ -69,11 +107,14 @@ public SpecificDatumReader(Schema writer, Schema reader) {
public SpecificDatumReader(Schema writer, Schema reader, SpecificData data) {
super(writer, reader, data);
trustedPackages.addAll(Arrays.asList(SERIALIZABLE_PACKAGES));
+ trustedClasses.addAll(Arrays.asList(SERIALIZABLE_CLASSES));
}
/** Construct given a {@link SpecificData}. */
public SpecificDatumReader(SpecificData data) {
super(data);
+ trustedPackages.addAll(Arrays.asList(SERIALIZABLE_PACKAGES));
+ trustedClasses.addAll(Arrays.asList(SERIALIZABLE_CLASSES));
}
/** Return the contained {@link SpecificData}. */
@@ -115,8 +156,8 @@ private Class getPropAsClass(Schema schema, String prop) {
if (name == null)
return null;
try {
+ checkSecurity(name);
Class clazz = ClassUtils.forName(getData().getClassLoader(), name);
- checkSecurity(clazz);
return clazz;
} catch (ClassNotFoundException e) {
throw new AvroRuntimeException(e);
@@ -127,31 +168,41 @@ private boolean trustAllPackages() {
return (trustedPackages.size() == 1 && "*".equals(trustedPackages.get(0)));
}
- private void checkSecurity(Class clazz) throws ClassNotFoundException {
- if (trustAllPackages() || clazz.isPrimitive()) {
+ private void checkSecurity(String className) throws ClassNotFoundException {
+ if (trustAllPackages() || PRIMITIVES.contains(className)) {
return;
}
- boolean found = false;
- Package thePackage = clazz.getPackage();
- if (thePackage != null) {
- for (String trustedPackage : getTrustedPackages()) {
- if (thePackage.getName().equals(trustedPackage) || thePackage.getName().startsWith(trustedPackage + ".")) {
- found = true;
- break;
- }
+ for (String trustedClass : getTrustedClasses()) {
+ if (className.equals(trustedClass)) {
+ return;
}
- if (!found) {
- throw new SecurityException("Forbidden " + clazz
- + "! This class is not trusted to be included in Avro schema using java-class. Please set org.apache.avro.SERIALIZABLE_PACKAGES system property with the packages you trust.");
+ }
+
+ for (String trustedPackage : getTrustedPackages()) {
+ if (className.startsWith(trustedPackage)) {
+ return;
}
}
+
+ throw new SecurityException("Forbidden " + className + "! This class is not trusted to be included in Avro "
+ + "schemas using java-class. Please set the system property org.apache.avro.SERIALIZABLE_CLASSES to the comma "
+ + "separated list of classes you trust. You can also set the system property "
+ + "org.apache.avro.SERIALIZABLE_PACKAGES to the comma separated list of the packages you trust.");
}
+ /**
+ * @deprecated Use getTrustedClasses() instead
+ */
+ @Deprecated
public final List getTrustedPackages() {
return trustedPackages;
}
+ public final List getTrustedClasses() {
+ return trustedClasses;
+ }
+
@Override
protected Object readRecord(Object old, Schema expected, ResolvingDecoder in) throws IOException {
SpecificData data = getSpecificData();
diff --git a/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflect.java b/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflect.java
index e3065d59b87..5eab3551ff0 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflect.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflect.java
@@ -570,6 +570,7 @@ void checkReadWrite(Object object) throws Exception {
}
void checkReadWrite(Object object, Schema s) throws Exception {
+
ReflectDatumWriter
diff --git a/lang/java/ipc/src/test/java/org/apache/avro/compiler/specific/TestSpecificCompiler.java b/lang/java/ipc/src/test/java/org/apache/avro/compiler/specific/TestSpecificCompiler.java
index 7c42ca9d9fc..c59d9e7a73f 100644
--- a/lang/java/ipc/src/test/java/org/apache/avro/compiler/specific/TestSpecificCompiler.java
+++ b/lang/java/ipc/src/test/java/org/apache/avro/compiler/specific/TestSpecificCompiler.java
@@ -74,7 +74,7 @@ public class TestSpecificCompiler {
@Test
public void testEsc() {
- assertEquals("\\\"", SpecificCompiler.javaEscape("\""));
+ assertEquals("\\\"", SpecificCompiler.escapeForJavaString("\""));
}
@Test
diff --git a/lang/java/mapred/pom.xml b/lang/java/mapred/pom.xml
index e6fb35e7864..0a83cdfb31e 100644
--- a/lang/java/mapred/pom.xml
+++ b/lang/java/mapred/pom.xml
@@ -23,7 +23,7 @@
avro-parent
org.apache.avro
- 1.11.4
+ 1.11.5
../
diff --git a/lang/java/maven-plugin/pom.xml b/lang/java/maven-plugin/pom.xml
index f1351a3fe63..9114dfd8f83 100644
--- a/lang/java/maven-plugin/pom.xml
+++ b/lang/java/maven-plugin/pom.xml
@@ -23,7 +23,7 @@
avro-parent
org.apache.avro
- 1.11.4
+ 1.11.5
../pom.xml
diff --git a/lang/java/perf/pom.xml b/lang/java/perf/pom.xml
index 73d86c702bd..b6dd4f1a069 100644
--- a/lang/java/perf/pom.xml
+++ b/lang/java/perf/pom.xml
@@ -23,7 +23,7 @@
avro-parent
org.apache.avro
- 1.11.4
+ 1.11.5
../
diff --git a/lang/java/pom.xml b/lang/java/pom.xml
index 77bd5803e06..d2ac4440c20 100644
--- a/lang/java/pom.xml
+++ b/lang/java/pom.xml
@@ -22,7 +22,7 @@
org.apache.avro
avro-toplevel
- 1.11.4
+ 1.11.5
../../pom.xml
diff --git a/lang/java/protobuf/pom.xml b/lang/java/protobuf/pom.xml
index bc92e9042a3..22245ea6d87 100644
--- a/lang/java/protobuf/pom.xml
+++ b/lang/java/protobuf/pom.xml
@@ -23,7 +23,7 @@
avro-parent
org.apache.avro
- 1.11.4
+ 1.11.5
../
diff --git a/lang/java/thrift/pom.xml b/lang/java/thrift/pom.xml
index a85f024b588..38989fb57bf 100644
--- a/lang/java/thrift/pom.xml
+++ b/lang/java/thrift/pom.xml
@@ -23,7 +23,7 @@
avro-parent
org.apache.avro
- 1.11.4
+ 1.11.5
../
diff --git a/lang/java/tools/pom.xml b/lang/java/tools/pom.xml
index 436cf8e1c85..87f7895b4b0 100644
--- a/lang/java/tools/pom.xml
+++ b/lang/java/tools/pom.xml
@@ -23,7 +23,7 @@
avro-parent
org.apache.avro
- 1.11.4
+ 1.11.5
../
diff --git a/lang/java/trevni/avro/pom.xml b/lang/java/trevni/avro/pom.xml
index a035f05a9f7..32c420f5e95 100644
--- a/lang/java/trevni/avro/pom.xml
+++ b/lang/java/trevni/avro/pom.xml
@@ -22,7 +22,7 @@
trevni-java
org.apache.avro
- 1.11.4
+ 1.11.5
../
diff --git a/lang/java/trevni/core/pom.xml b/lang/java/trevni/core/pom.xml
index 08a5fd57fa8..089f95ab25e 100644
--- a/lang/java/trevni/core/pom.xml
+++ b/lang/java/trevni/core/pom.xml
@@ -22,7 +22,7 @@
trevni-java
org.apache.avro
- 1.11.4
+ 1.11.5
../
diff --git a/lang/java/trevni/doc/pom.xml b/lang/java/trevni/doc/pom.xml
index fc6bae86a4d..28aa6ea82aa 100644
--- a/lang/java/trevni/doc/pom.xml
+++ b/lang/java/trevni/doc/pom.xml
@@ -22,7 +22,7 @@
trevni-java
org.apache.avro
- 1.11.4
+ 1.11.5
..
diff --git a/lang/java/trevni/pom.xml b/lang/java/trevni/pom.xml
index 064be245134..b005484aeb9 100644
--- a/lang/java/trevni/pom.xml
+++ b/lang/java/trevni/pom.xml
@@ -23,7 +23,7 @@
avro-parent
org.apache.avro
- 1.11.4
+ 1.11.5
../
diff --git a/lang/js/package-lock.json b/lang/js/package-lock.json
index cb61de31f17..f2d667dff99 100644
--- a/lang/js/package-lock.json
+++ b/lang/js/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "avro-js",
- "version": "1.11.4-SNAPSHOT",
+ "version": "1.11.5",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/lang/js/package.json b/lang/js/package.json
index 84383ce0b99..4c8678bc29a 100644
--- a/lang/js/package.json
+++ b/lang/js/package.json
@@ -1,6 +1,6 @@
{
"name": "avro-js",
- "version": "1.11.4",
+ "version": "1.11.5",
"author": "Avro Developers ",
"description": "JavaScript Avro implementation",
"contributors": [
diff --git a/lang/perl/Makefile.PL b/lang/perl/Makefile.PL
index ffac5e9d11b..13508b67197 100644
--- a/lang/perl/Makefile.PL
+++ b/lang/perl/Makefile.PL
@@ -26,10 +26,13 @@ license 'apache';
version $version;
readme_from 'lib/Avro.pm';
all_from 'lib/Avro.pm';
-build_requires 'Test::More', 0.88;
+configure_requires 'Module::Install';
+configure_requires 'Module::Install::ReadmeFromPod';
test_requires 'Math::BigInt';
test_requires 'Perl::Critic';
test_requires 'Test::Exception';
+test_requires 'Test::More', 0.88;
+test_requires 'Test::Pod';
requires 'Compress::Zlib';
requires 'Compress::Zstd';
requires 'Encode';
diff --git a/lang/py/avro/io.py b/lang/py/avro/io.py
index 7b5576697eb..15427c48302 100644
--- a/lang/py/avro/io.py
+++ b/lang/py/avro/io.py
@@ -644,9 +644,10 @@ def readers_schema(self, readers_schema: avro.schema.Schema) -> None:
def read(self, decoder: "BinaryDecoder") -> object:
if self.writers_schema is None:
raise avro.errors.IONotReadyException("Cannot read without a writer's schema.")
- if self.readers_schema is None:
- self.readers_schema = self.writers_schema
- return self.read_data(self.writers_schema, self.readers_schema, decoder)
+ reader_schema = self.readers_schema
+ if reader_schema is None:
+ reader_schema = self.writers_schema
+ return self.read_data(self.writers_schema, reader_schema, decoder)
def read_data(self, writers_schema: avro.schema.Schema, readers_schema: avro.schema.Schema, decoder: "BinaryDecoder") -> object:
# schema matching
diff --git a/lang/py/tox.ini b/lang/py/tox.ini
index e7bba45baf1..6a3c5d2d752 100644
--- a/lang/py/tox.ini
+++ b/lang/py/tox.ini
@@ -26,8 +26,8 @@ envlist =
py38
py39
py310
- pypy3.6
- pypy3.7
+ py311
+ pypy3.10
[coverage:run]
diff --git a/pom.xml b/pom.xml
index bf99f329c3e..7bf72f6e924 100644
--- a/pom.xml
+++ b/pom.xml
@@ -27,7 +27,7 @@
org.apache.avro
avro-toplevel
- 1.11.4
+ 1.11.5
pom
Apache Avro Toplevel
@@ -64,7 +64,7 @@
3.2.5
- 1723820671
+ 1754831786
diff --git a/share/VERSION.txt b/share/VERSION.txt
index 3d0e62313ce..e6dbb7c238f 100644
--- a/share/VERSION.txt
+++ b/share/VERSION.txt
@@ -1 +1 @@
-1.11.4
+1.11.5
diff --git a/share/docker/Dockerfile b/share/docker/Dockerfile
index c1c2565e593..b976f9772fa 100644
--- a/share/docker/Dockerfile
+++ b/share/docker/Dockerfile
@@ -114,8 +114,11 @@ RUN set -eux; \
ENV PATH="/opt/maven/bin:${PATH}"
# Install nodejs
+# The node deprecation warnings cause a 20 second sleep.
+# But mom, I'm not even tired!
RUN curl -sSL https://deb.nodesource.com/setup_14.x \
- | bash - \
+ | sed 's/sleep/echo "But mom!"/' \
+ | bash \
&& apt-get -qqy install nodejs \
&& apt-get -qqy clean \
&& npm install -g grunt-cli \
@@ -167,10 +170,24 @@ RUN curl -sSL https://cpanmin.us \
Module::Install::Repository \
&& rm -rf .cpanm
-# Install Python packages
-ENV PIP_NO_CACHE_DIR=off
+# Install Python3
+ENV PATH="${PATH}:/opt/pypy3.10/bin" \
+ PIP_NO_CACHE_DIR=off
+
+# https://docs.docker.com/engine/reference/builder/#automatic-platform-args-in-the-global-scope
+ARG BUILDARCH
+RUN case "${BUILDARCH:?}" in \
+ arm64) pypyarch=aarch64;; \
+ *) pypyarch=linux64;; \
+ esac \
+ && cd /opt \
+ && for url in https://downloads.python.org/pypy/pypy3.10-v7.3.12-"$pypyarch".tar.bz2; \
+ do curl -fsSL "$url" | tar -xvjpf -; \
+ done \
+ && ln -s pypy3.10* pypy3.10
# Install Python3 packages
+ENV PIP_NO_CACHE_DIR=off
RUN python3 -m pip install --upgrade pip setuptools wheel \
&& python3 -m pip install tox zstandard