Skip to content

Commit 3517938

Browse files
committed
#926 Fix using native client, password is limited to 255 bytes
(backport of #925)
1 parent 9e3140c commit 3517938

17 files changed

Lines changed: 370 additions & 16 deletions

src/docs/asciidoc/release_notes.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ This results in two minor breaking changes:
5353
** Presence of the NUL character (U+0000) in an identifier passed to `enquoteIdentifier` will result in a `SQLSyntaxErrorException`
5454
* Fixed: JDBC escapes should not be parsed inside dialect 3 delimited identifiers or dialect 1 string literals (https://github.com/FirebirdSQL/jaybird/issues/922[#922])
5555
* Fixed: `IndexOutOfBoundsException` in `FBCachedBlob.getBytes(long, int)` for position or length beyond end of data (https://github.com/FirebirdSQL/jaybird/issues/924[#924])
56+
* Fixed: Using native client, password is limited to 255 bytes (https://github.com/FirebirdSQL/jaybird/issues/926[#926])
5657
5758
[#jaybird-5-0-11-changelog]
5859
=== Jaybird 5.0.11

src/main/org/firebirdsql/gds/impl/DatabaseParameterBufferImp.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,17 @@ public ParameterTagMapping getTagMapping() {
5050
}
5151

5252
public enum DpbMetaData implements ParameterBufferMetaData {
53-
DPB_VERSION_1(ISCConstants.isc_dpb_version1, ArgumentType.TraditionalDpb),
53+
DPB_VERSION_1(ISCConstants.isc_dpb_version1, ArgumentType.TraditionalDpb) {
54+
@Override
55+
public boolean isUpgradable() {
56+
return true;
57+
}
58+
59+
@Override
60+
public ParameterBufferMetaData upgradeMetaData() {
61+
return DPB_VERSION_2;
62+
}
63+
},
5464
DPB_VERSION_2(ISCConstants.isc_dpb_version2, ArgumentType.Wide);
5565

5666
private final int dpbVersion;

src/main/org/firebirdsql/gds/impl/ParameterBufferBase.java

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
import java.util.ArrayList;
3535
import java.util.Iterator;
3636
import java.util.List;
37+
import java.util.Optional;
38+
import java.util.stream.Collectors;
3739

3840
/**
3941
* Base class for parameter buffers
@@ -45,7 +47,7 @@ public abstract class ParameterBufferBase implements ParameterBuffer, Serializab
4547
private final List<Argument> arguments = new ArrayList<>();
4648

4749
private final String defaultEncodingName;
48-
private final ParameterBufferMetaData parameterBufferMetaData;
50+
private ParameterBufferMetaData parameterBufferMetaData;
4951
private transient Encoding defaultEncoding;
5052

5153
/**
@@ -94,7 +96,21 @@ public final void addArgument(int argumentType, String value) {
9496

9597
@Override
9698
public final void addArgument(int argumentType, String value, Encoding encoding) {
97-
getArgumentsList().add(new StringArgument(argumentType, parameterBufferMetaData.getStringArgumentType(argumentType), value, encoding));
99+
getArgumentsList().add(createStringArgument(argumentType, value, encoding));
100+
}
101+
102+
private StringArgument createStringArgument(int argumentType, String value, Encoding encoding) {
103+
try {
104+
return new StringArgument(
105+
argumentType, parameterBufferMetaData.getStringArgumentType(argumentType), value, encoding);
106+
} catch (LengthOverflowException e) {
107+
if (tryUpgradeMetaData()) {
108+
// Do not inline parameterBufferMetaData or argument type; they might be different here than in the try
109+
return new StringArgument(
110+
argumentType, parameterBufferMetaData.getStringArgumentType(argumentType), value, encoding);
111+
}
112+
throw e;
113+
}
98114
}
99115

100116
@Override
@@ -119,7 +135,19 @@ public final void addArgument(int argumentType) {
119135

120136
@Override
121137
public final void addArgument(int type, byte[] content) {
122-
getArgumentsList().add(new ByteArrayArgument(type, parameterBufferMetaData.getByteArrayArgumentType(type), content));
138+
getArgumentsList().add(createByteArrayArgument(type, content));
139+
}
140+
141+
private ByteArrayArgument createByteArrayArgument(int type, byte[] content) {
142+
try {
143+
return new ByteArrayArgument(type, parameterBufferMetaData.getByteArrayArgumentType(type), content);
144+
} catch (LengthOverflowException e) {
145+
if (tryUpgradeMetaData()) {
146+
// Do not inline parameterBufferMetaData or argument type; they might be different here than in the try
147+
return new ByteArrayArgument(type, parameterBufferMetaData.getByteArrayArgumentType(type), content);
148+
}
149+
throw e;
150+
}
123151
}
124152

125153
@Override
@@ -153,6 +181,10 @@ public final boolean hasArgument(int type) {
153181
return false;
154182
}
155183

184+
protected Optional<Argument> findFirst(int type) {
185+
return arguments.stream().filter(argument -> argument.getType() == type).findFirst();
186+
}
187+
156188
@Override
157189
public final void removeArgument(int type) {
158190
final List<Argument> argumentsList = getArgumentsList();
@@ -227,6 +259,22 @@ public final boolean isEmpty() {
227259
return arguments.isEmpty();
228260
}
229261

262+
private boolean tryUpgradeMetaData() {
263+
if (!parameterBufferMetaData.isUpgradable()) return false;
264+
try {
265+
ParameterBufferMetaData newParameterBufferMetaData = parameterBufferMetaData.upgradeMetaData();
266+
List<Argument> newArguments = arguments.stream()
267+
.map(argument -> argument.transformTo(newParameterBufferMetaData))
268+
.collect(Collectors.toList());
269+
arguments.clear();
270+
arguments.addAll(newArguments);
271+
parameterBufferMetaData = newParameterBufferMetaData;
272+
return true;
273+
} catch (IllegalArgumentException e) {
274+
return false;
275+
}
276+
}
277+
230278
@Override
231279
public final boolean equals(Object other) {
232280
if (other == null || !(this.getClass().isAssignableFrom(other.getClass())))

src/main/org/firebirdsql/gds/impl/ParameterBufferMetaData.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,31 @@ default ArgumentType getByteArgumentType(int tag) {
106106
return getIntegerArgumentType(tag);
107107
}
108108

109+
/**
110+
* Returns if this metadata type is upgradable.
111+
* <p>
112+
* The default implementation always returns {@code false}.
113+
* </p>
114+
*
115+
* @return {@code true} if this type is upgradable
116+
* @see #upgradeMetaData()
117+
* @since 5.0.12
118+
*/
119+
default boolean isUpgradable() {
120+
return false;
121+
}
122+
123+
/**
124+
* The parameter buffer metadata that can be upgraded to.
125+
* <p>
126+
* The default implementation always returns {@code this}.
127+
* </p>
128+
*
129+
* @return the upgrade buffer metadata, returns this instance if {@link #isUpgradable()} returns {@code false}
130+
* @since 5.0.12
131+
*/
132+
default ParameterBufferMetaData upgradeMetaData() {
133+
return this;
134+
}
135+
109136
}

src/main/org/firebirdsql/gds/impl/ServiceParameterBufferImp.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,16 @@ public ArgumentType getSingleArgumentType(int tag) {
7474
}
7575
return ArgumentType.TraditionalDpb;
7676
}
77+
78+
@Override
79+
public boolean isUpgradable() {
80+
return true;
81+
}
82+
83+
@Override
84+
public ParameterBufferMetaData upgradeMetaData() {
85+
return SPB_VERSION_3_ATTACH;
86+
}
7787
},
7888
// Technically this has nothing to do with SPB version 2/3
7989
SPB_VERSION_2(ISCConstants.isc_spb_current_version) {

src/main/org/firebirdsql/gds/impl/argument/Argument.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
package org.firebirdsql.gds.impl.argument;
2020

2121
import org.firebirdsql.gds.Parameter;
22+
import org.firebirdsql.gds.impl.ParameterBufferMetaData;
2223

2324
import java.io.IOException;
2425
import java.io.OutputStream;
@@ -85,4 +86,17 @@ public long getValueAsLong() {
8586
*/
8687
public abstract int getLength();
8788

89+
/**
90+
* If needed, returns a new argument to transform to a suitable argument type, otherwise returns this instance.
91+
*
92+
* @param parameterBufferMetaData
93+
* parameter buffer metadata (used to determine the needed argument type)
94+
* @return either a new argument if transformation is needed, or this instance
95+
* @throws IllegalArgumentException
96+
* if transformation is needed, but the creation of the new instance fails (e.g. downgrading from
97+
* {@link ArgumentType#Wide} to {@link ArgumentType#TraditionalDpb}, and the value is too long)
98+
* @since 5.0.12
99+
*/
100+
public abstract Argument transformTo(ParameterBufferMetaData parameterBufferMetaData);
101+
88102
}

src/main/org/firebirdsql/gds/impl/argument/BigIntArgument.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.firebirdsql.encodings.Encoding;
2222
import org.firebirdsql.gds.ParameterBuffer;
2323
import org.firebirdsql.gds.VaxEncoding;
24+
import org.firebirdsql.gds.impl.ParameterBufferMetaData;
2425

2526
import java.io.IOException;
2627
import java.io.OutputStream;
@@ -81,6 +82,13 @@ public void copyTo(ParameterBuffer buffer, Encoding encoding) {
8182
buffer.addArgument(getType(), value);
8283
}
8384

85+
@Override
86+
public BigIntArgument transformTo(ParameterBufferMetaData parameterBufferMetaData) {
87+
ArgumentType newArgumentType = parameterBufferMetaData.getIntegerArgumentType(getType());
88+
if (newArgumentType == argumentType) return this;
89+
return new BigIntArgument(getType(), newArgumentType, value);
90+
}
91+
8492
@Override
8593
public boolean equals(Object other) {
8694
if (!(other instanceof BigIntArgument)) {

src/main/org/firebirdsql/gds/impl/argument/ByteArgument.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import org.firebirdsql.encodings.Encoding;
2222
import org.firebirdsql.gds.ParameterBuffer;
23+
import org.firebirdsql.gds.impl.ParameterBufferMetaData;
2324

2425
import java.io.IOException;
2526
import java.io.OutputStream;
@@ -76,6 +77,13 @@ public void copyTo(ParameterBuffer buffer, Encoding encoding) {
7677
buffer.addArgument(getType(), value);
7778
}
7879

80+
@Override
81+
public ByteArgument transformTo(ParameterBufferMetaData parameterBufferMetaData) {
82+
ArgumentType newArgumentType = parameterBufferMetaData.getByteArgumentType(getType());
83+
if (newArgumentType == argumentType) return this;
84+
return new ByteArgument(getType(), newArgumentType, value);
85+
}
86+
7987
@Override
8088
public boolean equals(Object other) {
8189
if (!(other instanceof ByteArgument)) {

src/main/org/firebirdsql/gds/impl/argument/ByteArrayArgument.java

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import org.firebirdsql.encodings.Encoding;
2222
import org.firebirdsql.gds.ParameterBuffer;
23+
import org.firebirdsql.gds.impl.ParameterBufferMetaData;
2324

2425
import java.io.IOException;
2526
import java.io.OutputStream;
@@ -38,12 +39,18 @@ public final class ByteArrayArgument extends TypedArgument {
3839
private final byte[] value;
3940

4041
/**
41-
* Initializes an instance of ByteArrayArgument.
42+
* Initialises an instance of ByteArrayArgument.
4243
*
4344
* @param type
44-
* Parameter type
45+
* parameter type
46+
* @param argumentType
47+
* argument type
4548
* @param value
46-
* Byte array with a maximum length defined by {@code argumentType}.
49+
* byte array
50+
* @throws IllegalArgumentException
51+
* if {@code type} is not valid for byte arrays, or if {@code value} is {@code null}
52+
* @throws LengthOverflowException
53+
* if the length of {@code value} exceeds {@link ArgumentType#getMaxLength()}
4754
*/
4855
public ByteArrayArgument(int type, ArgumentType argumentType, byte[] value) {
4956
super(type, argumentType);
@@ -56,7 +63,7 @@ public ByteArrayArgument(int type, ArgumentType argumentType, byte[] value) {
5663
throw new IllegalArgumentException("byte array value should not be null");
5764
}
5865
if (value.length > argumentType.getMaxLength()) {
59-
throw new IllegalArgumentException(
66+
throw new LengthOverflowException(
6067
String.format("byte array value should not be longer than %d bytes, length was %d",
6168
argumentType.getMaxLength(), value.length));
6269
}
@@ -84,11 +91,23 @@ public int getValueAsInt() {
8491
}
8592
}
8693

94+
// primarily intended for testing purposes
95+
public byte[] getValueAsBytes() {
96+
return value.clone();
97+
}
98+
8799
@Override
88100
public void copyTo(ParameterBuffer buffer, Encoding encoding) {
89101
buffer.addArgument(getType(), value.clone());
90102
}
91103

104+
@Override
105+
public ByteArrayArgument transformTo(ParameterBufferMetaData parameterBufferMetaData) {
106+
ArgumentType newArgumentType = parameterBufferMetaData.getByteArrayArgumentType(getType());
107+
if (newArgumentType == argumentType) return this;
108+
return new ByteArrayArgument(getType(), newArgumentType, value);
109+
}
110+
92111
@Override
93112
public boolean equals(Object other) {
94113
if (!(other instanceof ByteArrayArgument)) {
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// SPDX-FileCopyrightText: Copyright 2026 Mark Rotteveel
2+
// SPDX-License-Identifier: LGPL-2.1-or-later
3+
package org.firebirdsql.gds.impl.argument;
4+
5+
/**
6+
* Thrown by {@link StringArgument} and {@link ByteArrayArgument} if a value's length exceeds that of their
7+
* {@link ArgumentType}.
8+
*
9+
* @since 5.0.12
10+
*/
11+
public class LengthOverflowException extends IllegalArgumentException {
12+
13+
private static final long serialVersionUID = 5735116134576091931L;
14+
15+
LengthOverflowException(String message) {
16+
super(message);
17+
}
18+
19+
}

0 commit comments

Comments
 (0)