This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-csv.git
commit 42ded1cf3a29f511264c76e5e3380006957f8921 Author: Gary D. Gregory <garydgreg...@gmail.com> AuthorDate: Sat Mar 15 10:23:17 2025 -0400 Fix possible NullPointerException in Token.toString() --- src/changes/changes.xml | 1 + src/main/java/org/apache/commons/csv/Token.java | 14 +++--- .../java/org/apache/commons/csv/TokenTest.java | 50 ++++++++++++++++++++++ 3 files changed, 58 insertions(+), 7 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index f801b350..ba73a04a 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -50,6 +50,7 @@ <action type="fix" dev="ggregory" due-to="Gary Gregory">CSVParser.parse(Path, Charset, CSVFormat) with a null CSVFormat maps to CSVFormat.DEFAULT (like CSVParser.parse(Reader, CSVFormat)).</action> <action type="fix" dev="ggregory" due-to="Gary Gregory">CSVParser.parse(InputStream, Charset, CSVFormat) with a null CSVFormat maps to CSVFormat.DEFAULT (like CSVParser.parse(Reader, CSVFormat)).</action> <action type="fix" dev="ggregory" due-to="Gary Gregory">CSVParser.parse(*) methods with a null Charset maps to Charset.defaultCharset().</action> + <action type="fix" dev="ggregory" due-to="Gary Gregory">Fix possible NullPointerException in Token.toString().</action> <!-- ADD --> <action type="add" dev="ggregory" due-to="Gary Gregory">Define and use Maven property commons.jmh.version.</action> <action type="add" dev="ggregory" due-to="Gary Gregory">Add CSVFormat.Builder.setMaxRows(long).</action> diff --git a/src/main/java/org/apache/commons/csv/Token.java b/src/main/java/org/apache/commons/csv/Token.java index 9e63b944..17eb4c77 100644 --- a/src/main/java/org/apache/commons/csv/Token.java +++ b/src/main/java/org/apache/commons/csv/Token.java @@ -24,13 +24,13 @@ import static org.apache.commons.csv.Token.Type.INVALID; /** * Internal token representation. * <p> - * It is used as a contract between the lexer and the parser. + * This is used as a contract between the lexer and the parser. * </p> */ final class Token { enum Type { - /** Token has no valid content, i.e. is in its initialized state. */ + /** Token has no valid content, that is, is in its initialized state. */ INVALID, /** Token with content, at the beginning or in the middle of a line. */ @@ -47,13 +47,13 @@ final class Token { } /** Length of the initial token (content-)buffer */ - private static final int INITIAL_TOKEN_LENGTH = 50; + private static final int DEFAULT_CAPACITY = 50; /** Token type */ Token.Type type = INVALID; - /** The content buffer. */ - final StringBuilder content = new StringBuilder(INITIAL_TOKEN_LENGTH); + /** The content buffer, never null. */ + final StringBuilder content = new StringBuilder(DEFAULT_CAPACITY); /** Token ready flag: indicates a valid token with content (ready for the parser). */ boolean isReady; @@ -68,12 +68,12 @@ final class Token { } /** - * Eases IDE debugging. + * Converts the token state to a string to ease debugging. * * @return a string helpful for debugging. */ @Override public String toString() { - return type.name() + " [" + content.toString() + "]"; + return type + " [" + content.toString() + "]"; } } diff --git a/src/test/java/org/apache/commons/csv/TokenTest.java b/src/test/java/org/apache/commons/csv/TokenTest.java new file mode 100644 index 00000000..0f7f2f1e --- /dev/null +++ b/src/test/java/org/apache/commons/csv/TokenTest.java @@ -0,0 +1,50 @@ +/* + * 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.commons.csv; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +/** + * Tests {@link Token}. + */ +public class TokenTest { + + @ParameterizedTest + @EnumSource(Token.Type.class) + public void testToString(final Token.Type type) { + // Should never blow up + final Token token = new Token(); + final String resetName = Token.Type.INVALID.name(); + assertTrue(token.toString().contains(resetName)); + token.reset(); + assertTrue(token.toString().contains(resetName)); + token.type = null; + assertFalse(token.toString().isEmpty()); + token.reset(); + token.type = type; + assertTrue(token.toString().contains(type.name())); + token.content.setLength(1000); + assertTrue(token.toString().contains(type.name())); + } +}