Repository: cassandra Updated Branches: refs/heads/trunk 00a34c791 -> 288ffca73
Fix IOOBE when inserting bad tuple w/ string literal Patch by Benjamin Lerer; reviewed by Tyler Hobbs for CASSANDRA-9559 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/c2332706 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/c2332706 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/c2332706 Branch: refs/heads/trunk Commit: c233270643d0a887dc84ae90573176eb52f8ca93 Parents: 1119983 Author: blerer <benjamin.le...@datastax.com> Authored: Fri Jun 26 12:25:05 2015 -0500 Committer: Tyler Hobbs <tylerlho...@gmail.com> Committed: Fri Jun 26 12:25:05 2015 -0500 ---------------------------------------------------------------------- CHANGES.txt | 2 ++ .../apache/cassandra/db/marshal/TupleType.java | 9 +++++-- .../cql3/validation/entities/TupleTypeTest.java | 27 +++++++++++++++++++- 3 files changed, 35 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/c2332706/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 7f4ca28..874c8ee 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,6 @@ 2.1.8 + * Fix IndexOutOfBoundsException when inserting tuple with too many + elements using the string literal notation (CASSANDRA-9559) * Allow JMX over SSL directly from nodetool (CASSANDRA-9090) * Fix incorrect result for IN queries where column not found (CASSANDRA-9540) * Enable describe on indices (CASSANDRA-7814) http://git-wip-us.apache.org/repos/asf/cassandra/blob/c2332706/src/java/org/apache/cassandra/db/marshal/TupleType.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/marshal/TupleType.java b/src/java/org/apache/cassandra/db/marshal/TupleType.java index ddaf53f..e07319b 100644 --- a/src/java/org/apache/cassandra/db/marshal/TupleType.java +++ b/src/java/org/apache/cassandra/db/marshal/TupleType.java @@ -18,18 +18,18 @@ package org.apache.cassandra.db.marshal; import java.nio.ByteBuffer; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; import com.google.common.base.Objects; +import org.apache.cassandra.exceptions.InvalidRequestException; + import org.apache.cassandra.cql3.CQL3Type; import org.apache.cassandra.exceptions.ConfigurationException; import org.apache.cassandra.exceptions.SyntaxException; import org.apache.cassandra.serializers.*; import org.apache.cassandra.utils.ByteBufferUtil; -import org.apache.cassandra.utils.Pair; /** * This is essentially like a CompositeType, but it's not primarily meant for comparison, just @@ -212,6 +212,11 @@ public class TupleType extends AbstractType<ByteBuffer> { // Split the input on non-escaped ':' characters List<String> fieldStrings = AbstractCompositeType.split(source); + + if (fieldStrings.size() > size()) + throw new MarshalException(String.format("Invalid tuple literal: too many elements. Type %s expects %d but got %d", + asCQL3Type(), size(), fieldStrings.size())); + ByteBuffer[] fields = new ByteBuffer[fieldStrings.size()]; for (int i = 0; i < fieldStrings.size(); i++) { http://git-wip-us.apache.org/repos/asf/cassandra/blob/c2332706/test/unit/org/apache/cassandra/cql3/validation/entities/TupleTypeTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/TupleTypeTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/TupleTypeTest.java index 2d145de..177def7 100644 --- a/test/unit/org/apache/cassandra/cql3/validation/entities/TupleTypeTest.java +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/TupleTypeTest.java @@ -92,12 +92,37 @@ public class TupleTypeTest extends CQLTester } @Test + public void testTupleFromString() throws Throwable + { + createTable("CREATE TABLE %s (k int, c int, t frozen<tuple<int, text>>, PRIMARY KEY (k, c))"); + + execute("INSERT INTO %s (k, c, t) VALUES (0, 0, '0:0')"); + execute("INSERT INTO %s (k, c, t) VALUES (0, 1, '0:1')"); + execute("INSERT INTO %s (k, c, t) VALUES (0, 2, '1')"); + execute("INSERT INTO %s (k, c, t) VALUES (0, 3, '1:1\\:1')"); + execute("INSERT INTO %s (k, c, t) VALUES (0, 4, '@:1')"); + + assertAllRows( + row(0, 0, tuple(0, "0")), + row(0, 1, tuple(0, "1")), + row(0, 2, tuple(1)), + row(0, 3, tuple(1, "1:1")), + row(0, 4, tuple(null, "1")) + ); + + assertInvalidMessage("Invalid tuple literal: too many elements. Type tuple<int, text> expects 2 but got 3", + "INSERT INTO %s(k, t) VALUES (1,'1:2:3')"); + } + + @Test public void testInvalidQueries() throws Throwable { createTable("CREATE TABLE %s (k int PRIMARY KEY, t frozen<tuple<int, text, double>>)"); assertInvalidSyntax("INSERT INTO %s (k, t) VALUES (0, ())"); - assertInvalid("INSERT INTO %s (k, t) VALUES (0, (2, 'foo', 3.1, 'bar'))"); + + assertInvalidMessage("Invalid tuple literal for t: too many elements. Type tuple<int, text, double> expects 3 but got 4", + "INSERT INTO %s (k, t) VALUES (0, (2, 'foo', 3.1, 'bar'))"); } /**