github-advanced-security[bot] commented on code in PR #2885: URL: https://github.com/apache/avro/pull/2885#discussion_r1586491528
########## lang/java/avro/src/main/java/org/apache/avro/JsonSchemaFormatter.java: ########## @@ -0,0 +1,33 @@ +/* + * 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 + * + * https://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.avro; + +public class JsonSchemaFormatter implements SchemaFormatter { + private final boolean prettyPrinted; + + public JsonSchemaFormatter(boolean prettyPrinted) { + this.prettyPrinted = prettyPrinted; + } + + @Override + public String format(Schema schema) { + // TODO: Move the toString implementation here and have Schema#toString() + // use SchemaFormatter with the formats "json/pretty" and "json/inline" + return schema.toString(prettyPrinted); Review Comment: ## Deprecated method or constructor invocation Invoking [Schema.toString](1) should be avoided because it has been deprecated. [Show more details](https://github.com/apache/avro/security/code-scanning/3214) ########## lang/java/idl/src/test/java/org/apache/avro/util/IdlUtilsTest.java: ########## @@ -0,0 +1,195 @@ +/* + * 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 + * + * https://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.avro.util; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringWriter; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.Map; + +import com.fasterxml.jackson.core.JsonGenerator; +import org.apache.avro.AvroRuntimeException; +import org.apache.avro.JsonProperties; +import org.apache.avro.Protocol; +import org.apache.avro.Schema; +import org.apache.avro.idl.IdlFile; +import org.apache.avro.idl.IdlReader; +import org.junit.jupiter.api.Test; + +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; +import static java.util.Objects.requireNonNull; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class IdlUtilsTest { + @Test + public void idlUtilsUtilitiesThrowRuntimeExceptionsOnProgrammerError() { + assertThrows(IllegalStateException.class, () -> IdlUtils.getField(Object.class, "noSuchField"), "Programmer error"); + assertThrows(IllegalStateException.class, + () -> IdlUtils.getFieldValue(String.class.getDeclaredField("value"), "anything"), "Programmer error"); + + assertEquals("foo", IdlUtils.uncheckExceptions(() -> "foo")); + assertThrows(IllegalArgumentException.class, () -> IdlUtils.uncheckExceptions(() -> { + throw new IllegalArgumentException("Oops"); + }), "Oops"); + assertThrows(AvroRuntimeException.class, () -> IdlUtils.uncheckExceptions(() -> { + throw new IOException("Oops"); + }), "Oops"); + } + + @Test + public void validateHappyFlowForProtocol() throws IOException { + Protocol protocol = parseIdlResource("idl_utils_test_protocol.avdl").getProtocol(); + + StringWriter buffer = new StringWriter(); + IdlUtils.writeIdlProtocol(buffer, protocol); + + assertEquals(getResourceAsString("idl_utils_test_protocol.avdl"), buffer.toString()); + } + + private IdlFile parseIdlResource(String name) throws IOException { + IdlFile idlFile; + IdlReader idlReader = new IdlReader(); + try (InputStream stream = getClass().getResourceAsStream(name)) { Review Comment: ## Unsafe use of getResource The idiom getClass().getResource() is unsafe for classes that may be extended. [Show more details](https://github.com/apache/avro/security/code-scanning/3252) ########## lang/java/idl/src/main/java/org/apache/avro/util/IdlUtils.java: ########## @@ -0,0 +1,541 @@ +/* + * 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 + * + * https://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.avro.util; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.util.MinimalPrettyPrinter; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import org.apache.avro.AvroRuntimeException; +import org.apache.avro.JsonProperties; +import org.apache.avro.LogicalTypes; +import org.apache.avro.Protocol; +import org.apache.avro.Schema; + +import java.io.IOException; +import java.io.Writer; +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static java.util.Arrays.asList; +import static java.util.Collections.emptyList; +import static java.util.Collections.singleton; +import static java.util.Collections.singletonList; +import static java.util.Collections.unmodifiableSet; +import static java.util.Objects.requireNonNull; + +public final class IdlUtils { + static final ObjectMapper MAPPER; + private static final Function<Schema.Field, JsonNode> DEFAULT_VALUE; + private static final Pattern NEWLINE_PATTERN = Pattern.compile("(?U)\\R"); + private static final String NEWLINE = System.lineSeparator(); + private static final Set<String> KEYWORDS = unmodifiableSet(new HashSet<>( + asList("array", "boolean", "bytes", "date", "decimal", "double", "enum", "error", "false", "fixed", "float", + "idl", "import", "int", "local_timestamp_ms", "long", "map", "namespace", "null", "oneway", "protocol", + "record", "schema", "string", "throws", "timestamp_ms", "time_ms", "true", "union", "uuid", "void"))); + private static final EnumSet<Schema.Type> NULLABLE_TYPES = EnumSet + .complementOf(EnumSet.of(Schema.Type.ARRAY, Schema.Type.MAP, Schema.Type.UNION)); + + static { + SimpleModule module = new SimpleModule(); + module.addSerializer(new StdSerializer<JsonProperties.Null>(JsonProperties.Null.class) { + @Override + public void serialize(JsonProperties.Null value, JsonGenerator gen, SerializerProvider provider) + throws IOException { + gen.writeNull(); + } + }); + module.addSerializer(new StdSerializer<byte[]>(byte[].class) { + @Override + public void serialize(byte[] value, JsonGenerator gen, SerializerProvider provider) throws IOException { + MAPPER.writeValueAsString(new String(value, StandardCharsets.ISO_8859_1)); + } + }); + + ObjectMapper jsonMapper = getFieldValue(getField(Schema.class, "MAPPER"), null); + MAPPER = jsonMapper.copy().registerModule(module).disable(DeserializationFeature.READ_ENUMS_USING_TO_STRING) + .disable(SerializationFeature.WRITE_ENUMS_USING_INDEX, SerializationFeature.WRITE_ENUMS_USING_TO_STRING) + .enable(SerializationFeature.INDENT_OUTPUT).setDefaultPrettyPrinter(new MinimalPrettyPrinter() { + @Override + public void writeObjectEntrySeparator(JsonGenerator jg) throws IOException { + jg.writeRaw(','); + jg.writeRaw(' '); + } + + @Override + public void writeArrayValueSeparator(JsonGenerator jg) throws IOException { + jg.writeRaw(','); + jg.writeRaw(' '); + } + }); + + java.lang.reflect.Field defaultValueField = getField(Schema.Field.class, "defaultValue"); + DEFAULT_VALUE = field -> getFieldValue(defaultValueField, field); + } + + static java.lang.reflect.Field getField(Class<?> type, String name) { + try { + java.lang.reflect.Field field = type.getDeclaredField(name); + field.setAccessible(true); + return field; + } catch (NoSuchFieldException e) { + throw new IllegalStateException("Programmer error", e); + } + } + + static <T> T getFieldValue(java.lang.reflect.Field field, Object owner) { + try { + return (T) field.get(owner); + } catch (IllegalAccessException e) { + throw new IllegalStateException("Programmer error", e); + } + } + + private IdlUtils() { + // Utility class: do not instantiate. + } + + /** + * Calls the given callable, wrapping any checked exception in an + * {@link AvroRuntimeException}. + * + * @param callable the callable to call + * @return the result of the callable + */ + public static <T> T uncheckExceptions(Callable<T> callable) { + try { + return requireNonNull(callable).call(); + } catch (RuntimeException e) { + throw e; + } catch (Throwable e) { + throw new AvroRuntimeException(e.getMessage(), e); + } + } + + public static void writeIdlSchema(Writer writer, Schema schema) throws IOException { + writeIdlSchemas(writer, schema.getNamespace(), singleton(schema)); + } + + public static void writeIdlSchemas(Writer writer, String namespace, Collection<Schema> schemas) throws IOException { + if (schemas.isEmpty()) { + throw new IllegalArgumentException("Cannot write 0 schemas"); + } + if (namespace != null) { + writer.append("namespace "); + writer.append(namespace); + writer.append(";"); + writer.append(NEWLINE); + writer.append(NEWLINE); + } + + Set<String> alreadyDeclared = new HashSet<>(4); + Set<Schema> toDeclare = new LinkedHashSet<>(); + if (schemas.size() == 1) { + Schema schema = schemas.iterator().next(); + writer.append("schema "); + // Note: as alreadyDeclared is empty, writeFieldSchema adds schema to toDeclare + writeFieldSchema(schema, writer, alreadyDeclared, toDeclare, namespace); + writer.append(";"); + writer.append(NEWLINE); + writer.append(NEWLINE); + } else { + toDeclare.addAll(schemas); + } + + while (!toDeclare.isEmpty()) { + if (!alreadyDeclared.isEmpty()) { + writer.append(NEWLINE); + } + Iterator<Schema> iterator = toDeclare.iterator(); + Schema s = iterator.next(); + iterator.remove(); + writeSchema(s, false, writer, namespace, alreadyDeclared, toDeclare); + } + } + + public static void writeIdlProtocol(Writer writer, Protocol protocol) throws IOException { + final String protocolFullName = protocol.getName(); + final int lastDotPos = protocolFullName.lastIndexOf("."); + final String protocolNameSpace; + if (lastDotPos < 0) { + protocolNameSpace = protocol.getNamespace(); + } else if (lastDotPos > 0) { + protocolNameSpace = protocolFullName.substring(0, lastDotPos); + } else { + protocolNameSpace = null; + } + writeIdlProtocol(writer, protocol, protocolNameSpace, protocolFullName.substring(lastDotPos + 1), + protocol.getTypes(), protocol.getMessages().values()); + } + + public static void writeIdlProtocol(Writer writer, Schema schema) throws IOException { + final JsonProperties emptyProperties = Schema.create(Schema.Type.NULL); + writeIdlProtocol(writer, emptyProperties, schema.getNamespace(), "Protocol", singletonList(schema), emptyList()); + } + + public static void writeIdlProtocol(Writer writer, JsonProperties properties, String protocolNameSpace, + String protocolName, Collection<Schema> schemas, Collection<Protocol.Message> messages) throws IOException { + if (protocolNameSpace != null) { + writer.append("@namespace(\"").append(protocolNameSpace).append("\")").append(NEWLINE); + } + writeJsonProperties(properties, singleton("namespace"), writer, ""); + writer.append("protocol ").append(requireNonNull(safeName(protocolName))).append(" {").append(NEWLINE); + + Set<String> alreadyDeclared = new HashSet<>(4); + Set<Schema> toDeclare = new LinkedHashSet<>(schemas); + boolean first = true; + while (!toDeclare.isEmpty()) { + if (!first) { + writer.append(NEWLINE); + } + Iterator<Schema> iterator = toDeclare.iterator(); + Schema schema = iterator.next(); + iterator.remove(); + writeSchema(schema, true, writer, protocolNameSpace, alreadyDeclared, toDeclare); + first = false; + } + if (!schemas.isEmpty() && !messages.isEmpty()) { + writer.append(NEWLINE); + } + for (Protocol.Message message : messages) { + writeMessage(message, writer, protocolNameSpace, alreadyDeclared); + } + writer.append("}").append(NEWLINE); + } + + private static String safeName(String name) { + if (KEYWORDS.contains(name)) { + return String.format("`%s`", name); + } + return name; + } + + private static void writeSchema(Schema schema, boolean insideProtocol, Writer writer, String defaultNamespace, + Set<String> alreadyDeclared, Set<Schema> toDeclare) throws IOException { + String indent = insideProtocol ? " " : ""; + Schema.Type type = schema.getType(); + writeSchemaAttributes(indent, schema, writer); + String namespace = schema.getNamespace(); // Fails for unnamed schema types (other types than record, enum & fixed) + if (!Objects.equals(namespace, defaultNamespace)) { + writer.append(indent).append("@namespace(\"").append(namespace).append("\")").append(NEWLINE); + } + Set<String> schemaAliases = schema.getAliases(); + if (!schemaAliases.isEmpty()) { + writer.append(indent).append("@aliases(").append(MAPPER.writeValueAsString(schemaAliases)).append(")") + .append(NEWLINE); + } + String schemaName = safeName(schema.getName()); + if (type == Schema.Type.RECORD) { + String declarationType = schema.isError() ? "error" : "record"; + writer.append(indent).append("").append(declarationType).append(" ").append(schemaName).append(" {") + .append(NEWLINE); + alreadyDeclared.add(schema.getFullName()); + for (Schema.Field field : schema.getFields()) { + writeField(schema.getNamespace(), field, writer, alreadyDeclared, toDeclare, + insideProtocol ? FieldIndent.INSIDE_PROTOCOL : FieldIndent.TOPLEVEL_SCHEMA); + writer.append(";").append(NEWLINE); + } + writer.append(indent).append("}").append(NEWLINE); + } else if (type == Schema.Type.ENUM) { + writer.append(indent).append("enum ").append(schemaName).append(" {").append(NEWLINE); + alreadyDeclared.add(schema.getFullName()); + Iterator<String> i = schema.getEnumSymbols().iterator(); + if (i.hasNext()) { + writer.append(indent).append(" ").append(i.next()); + while (i.hasNext()) { + writer.append(", "); + writer.append(i.next()); + } + } else { + throw new AvroRuntimeException("Enum schema must have at least a symbol " + schema); + } + writer.append(NEWLINE).append(indent).append("}").append(NEWLINE); + } else /* (type == Schema.Type.FIXED) */ { + writer.append(indent).append("fixed ").append(schemaName).append('(') + .append(Integer.toString(schema.getFixedSize())).append(");").append(NEWLINE); + alreadyDeclared.add(schema.getFullName()); + } + } + + private static void writeField(String namespace, Schema.Field field, Writer writer, Set<String> alreadyDeclared, + Set<Schema> toDeclare, FieldIndent fieldIndent) throws IOException { + // Note: indentField must not be NONE if any field of the containing + // record/method has documentation + switch (fieldIndent) { Review Comment: ## Missing enum case in switch Switch statement does not have a case for [NONE](1). [Show more details](https://github.com/apache/avro/security/code-scanning/3251) ########## lang/java/idl/src/main/java/org/apache/avro/idl/IdlSchemaParser.java: ########## @@ -27,14 +27,17 @@ import java.util.regex.Pattern; public class IdlSchemaParser implements FormattedSchemaParser { + private static final Pattern START_OF_IDL_PATTERN = Pattern.compile("\\A" + // Start of input + "(?:\\s*|/\\*(?:[^*]|\\*(?!/))*\\*/|//(?:(?!\\R).)*\\R)*" + // Initial whitespace & comments + "(?:@|(?:namespace|schema|protocol|record|enum|fixed|import)\\s)", // First keyword mor @ Review Comment: ## Inefficient regular expression This part of the regular expression may cause exponential backtracking on strings starting with 'A//' and containing many repetitions of 'R//'. [Show more details](https://github.com/apache/avro/security/code-scanning/3212) ########## lang/java/idl/src/test/java/org/apache/avro/util/IdlUtilsTest.java: ########## @@ -0,0 +1,195 @@ +/* + * 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 + * + * https://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.avro.util; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringWriter; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.Map; + +import com.fasterxml.jackson.core.JsonGenerator; +import org.apache.avro.AvroRuntimeException; +import org.apache.avro.JsonProperties; +import org.apache.avro.Protocol; +import org.apache.avro.Schema; +import org.apache.avro.idl.IdlFile; +import org.apache.avro.idl.IdlReader; +import org.junit.jupiter.api.Test; + +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; +import static java.util.Objects.requireNonNull; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class IdlUtilsTest { + @Test + public void idlUtilsUtilitiesThrowRuntimeExceptionsOnProgrammerError() { + assertThrows(IllegalStateException.class, () -> IdlUtils.getField(Object.class, "noSuchField"), "Programmer error"); + assertThrows(IllegalStateException.class, + () -> IdlUtils.getFieldValue(String.class.getDeclaredField("value"), "anything"), "Programmer error"); + + assertEquals("foo", IdlUtils.uncheckExceptions(() -> "foo")); + assertThrows(IllegalArgumentException.class, () -> IdlUtils.uncheckExceptions(() -> { + throw new IllegalArgumentException("Oops"); + }), "Oops"); + assertThrows(AvroRuntimeException.class, () -> IdlUtils.uncheckExceptions(() -> { + throw new IOException("Oops"); + }), "Oops"); + } + + @Test + public void validateHappyFlowForProtocol() throws IOException { + Protocol protocol = parseIdlResource("idl_utils_test_protocol.avdl").getProtocol(); + + StringWriter buffer = new StringWriter(); + IdlUtils.writeIdlProtocol(buffer, protocol); + + assertEquals(getResourceAsString("idl_utils_test_protocol.avdl"), buffer.toString()); + } + + private IdlFile parseIdlResource(String name) throws IOException { + IdlFile idlFile; + IdlReader idlReader = new IdlReader(); + try (InputStream stream = getClass().getResourceAsStream(name)) { + idlFile = idlReader.parse(requireNonNull(stream)); + } + return idlFile; + } + + private String getResourceAsString(String name) throws IOException { + StringWriter schemaBuffer = new StringWriter(); + try (InputStreamReader reader = new InputStreamReader(requireNonNull(getClass().getResourceAsStream(name)))) { Review Comment: ## Unsafe use of getResource The idiom getClass().getResource() is unsafe for classes that may be extended. [Show more details](https://github.com/apache/avro/security/code-scanning/3253) ########## lang/java/idl/src/main/java/org/apache/avro/idl/IdlSchemaParser.java: ########## @@ -27,14 +27,17 @@ import java.util.regex.Pattern; public class IdlSchemaParser implements FormattedSchemaParser { + private static final Pattern START_OF_IDL_PATTERN = Pattern.compile("\\A" + // Start of input + "(?:\\s*|/\\*(?:[^*]|\\*(?!/))*\\*/|//(?:(?!\\R).)*\\R)*" + // Initial whitespace & comments + "(?:@|(?:namespace|schema|protocol|record|enum|fixed|import)\\s)", // First keyword mor @ Review Comment: ## Inefficient regular expression This part of the regular expression may cause exponential backtracking on strings starting with 'A' and containing many repetitions of ' '. [Show more details](https://github.com/apache/avro/security/code-scanning/3211) ########## lang/java/avro/src/test/java/org/apache/avro/SchemaFormatterTest.java: ########## @@ -0,0 +1,89 @@ +/* + * 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 + * + * https://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.avro; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class SchemaFormatterTest { + + @Test + void validateDefaultNaming() { + assertEquals("json", new JsonSchemaFormatterFactory().formatName()); + assertThrows(AvroRuntimeException.class, () -> new Wrongly_Named_SchemaFormatterFactory().formatName()); + assertThrows(AvroRuntimeException.class, () -> new SchemaFormatterFactoryWithOddName().formatName()); + } + + @Test + void validateJsonFormatDefaultsToPrettyPrinting() { + Schema schema = Schema.createFixed("ns.Fixed", null, null, 16); + assertEquals(SchemaFormatter.format("json", schema), SchemaFormatter.format("json/pretty", schema)); + } + + @Test + void validateSupportForPrettyJsonFormat() { + Schema schema = Schema.createFixed("ns.Fixed", null, null, 16); + assertEquals("{\n \"type\" : \"fixed\",\n \"name\" : \"Fixed\",\n \"namespace\" : \"ns\",\n \"size\" : 16\n}", + SchemaFormatter.format("json/pretty", schema)); + } + + @Test + void validateSupportForInlineJsonFormat() { + Schema schema = Schema.createFixed("ns.Fixed", null, null, 16); + assertEquals("{\"type\":\"fixed\",\"name\":\"Fixed\",\"namespace\":\"ns\",\"size\":16}", + SchemaFormatter.format("json/inline", schema)); + } + + @Test + void checkThatJsonHasNoExtraVariant() { + Schema schema = Schema.createFixed("ns.Fixed", null, null, 16); Review Comment: ## Unread local variable Variable 'Schema schema' is never read. [Show more details](https://github.com/apache/avro/security/code-scanning/3213) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
