diff --git a/CHANGES.txt b/CHANGES.txt index 0fc564e776..67985868f0 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -17,6 +17,7 @@ * dropping of a materialized view creates a snapshot with dropped- prefix (CASSANDRA-17415) * Validate existence of DCs when repairing (CASSANDRA-17407) Merged from 3.0: + * Fix data corruption in AbstractCompositeType due to static boolean byte buffers (CASSANDRA-14752) * Add procps dependency to RPM/Debian packages (CASSANDRA-17516) * Suppress CVE-2021-44521 (CASSANDRA-17492) * ConnectionLimitHandler may leaks connection count if remote connection drops (CASSANDRA-17252) diff --git a/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java b/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java index 24d283457e..18007fb711 100644 --- a/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java +++ b/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java @@ -208,8 +208,8 @@ public abstract class AbstractCompositeType extends AbstractType public ByteBuffer fromString(String source) { List parts = split(source); - List components = new ArrayList(parts.size()); - List comparators = new ArrayList(parts.size()); + List components = new ArrayList<>(parts.size()); + List comparators = new ArrayList<>(parts.size()); int totalLength = 0, i = 0; boolean lastByteIsOne = false; boolean lastByteIsMinusOne = false; @@ -244,7 +244,7 @@ public abstract class AbstractCompositeType extends AbstractType { comparators.get(i).serializeComparator(bb); ByteBufferUtil.writeShortLength(bb, component.remaining()); - bb.put(component); // it's ok to consume component as we won't use it anymore + bb.put(component.duplicate()); // it's not ok to consume component as we did not create it (CASSANDRA-14752) bb.put((byte)0); ++i; } diff --git a/test/distributed/org/apache/cassandra/distributed/test/BooleanTest.java b/test/distributed/org/apache/cassandra/distributed/test/BooleanTest.java new file mode 100644 index 0000000000..fa6722d9a9 --- /dev/null +++ b/test/distributed/org/apache/cassandra/distributed/test/BooleanTest.java @@ -0,0 +1,45 @@ +/* + * 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.cassandra.distributed.test; + +import org.junit.Assert; +import org.junit.Test; + +import org.apache.cassandra.distributed.Cluster; +import org.apache.cassandra.distributed.api.ConsistencyLevel; +import org.apache.cassandra.serializers.BooleanSerializer; + +public class BooleanTest extends TestBaseImpl +{ + @Test + public void booleanTest() throws Throwable + { + try(Cluster cluster = init(Cluster.build(1).start())) + { + cluster.schemaChange("create table " + KEYSPACE + ".tbl (id int, ck boolean, t int, primary key ((id, ck)))"); + for (int i = 0; i < 10; i++) + cluster.coordinator(1).execute(withKeyspace("insert into %s.tbl (id, ck, t) values (?, true, ?)"), ConsistencyLevel.ALL, i, i); + cluster.get(1).nodetoolResult("getsstables", KEYSPACE, "tbl", "1:true"); + cluster.forEach(i -> i.runOnInstance(() -> { + Assert.assertEquals(0, BooleanSerializer.instance.serialize(true).position()); + Assert.assertEquals(0, BooleanSerializer.instance.serialize(false).position()); + })); + } + } +} diff --git a/test/unit/org/apache/cassandra/db/SchemaCQLHelperTest.java b/test/unit/org/apache/cassandra/db/SchemaCQLHelperTest.java index b928ebfe6d..8cb1e1508a 100644 --- a/test/unit/org/apache/cassandra/db/SchemaCQLHelperTest.java +++ b/test/unit/org/apache/cassandra/db/SchemaCQLHelperTest.java @@ -476,6 +476,6 @@ public class SchemaCQLHelperTest extends CQLTester cfs.getSSTablesForKey("false:true"); execute("insert into %s (t_id, id, ck, nk) VALUES (true, true, false, true)"); - assertRows(execute("select t_id, id, ck, nk from %s"), row(true, false, false, true), row(true, true, false, true)); + assertRows(execute("select t_id, id, ck, nk from %s"), row(true, true, false, true), row(true, false, false, true)); } }