Skip to content

Commit 4aada2c

Browse files
committed
#925 Fix using native client, password is limited to 255 bytes
1 parent f989cc7 commit 4aada2c

16 files changed

Lines changed: 358 additions & 21 deletions

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

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// SPDX-FileCopyrightText: Copyright 2003 Ryan Baldwin
22
// SPDX-FileCopyrightText: Copyright 2005-2006 Roman Rokytskyy
3-
// SPDX-FileCopyrightText: Copyright 2014-2023 Mark Rotteveel
3+
// SPDX-FileCopyrightText: Copyright 2014-2026 Mark Rotteveel
44
// SPDX-License-Identifier: LGPL-2.1-or-later
55
package org.firebirdsql.gds.impl;
66

@@ -41,7 +41,17 @@ public ParameterTagMapping getTagMapping() {
4141
}
4242

4343
public enum DpbMetaData implements ParameterBufferMetaData {
44-
DPB_VERSION_1(ISCConstants.isc_dpb_version1, ArgumentType.TraditionalDpb),
44+
DPB_VERSION_1(ISCConstants.isc_dpb_version1, ArgumentType.TraditionalDpb) {
45+
@Override
46+
public boolean isUpgradable() {
47+
return true;
48+
}
49+
50+
@Override
51+
public ParameterBufferMetaData upgradeMetaData() {
52+
return DPB_VERSION_2;
53+
}
54+
},
4555
DPB_VERSION_2(ISCConstants.isc_dpb_version2, ArgumentType.Wide);
4656

4757
private final int dpbVersion;

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

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public abstract class ParameterBufferBase implements ParameterBuffer, Serializab
4141
private final List<Argument> arguments = new ArrayList<>();
4242

4343
private final String defaultEncodingName;
44-
private final ParameterBufferMetaData parameterBufferMetaData;
44+
private ParameterBufferMetaData parameterBufferMetaData;
4545
private transient Encoding defaultEncoding;
4646

4747
/**
@@ -90,8 +90,21 @@ public final void addArgument(int argumentType, String value) {
9090

9191
@Override
9292
public final void addArgument(int argumentType, String value, Encoding encoding) {
93-
addArgument(new StringArgument(
94-
argumentType, parameterBufferMetaData.getStringArgumentType(argumentType), value, encoding));
93+
addArgument(createStringArgument(argumentType, value, encoding));
94+
}
95+
96+
private StringArgument createStringArgument(int argumentType, String value, Encoding encoding) {
97+
try {
98+
return new StringArgument(
99+
argumentType, parameterBufferMetaData.getStringArgumentType(argumentType), value, encoding);
100+
} catch (LengthOverflowException e) {
101+
if (tryUpgradeMetaData()) {
102+
// Do not inline parameterBufferMetaData or argument type; they might be different here than in the try
103+
return new StringArgument(
104+
argumentType, parameterBufferMetaData.getStringArgumentType(argumentType), value, encoding);
105+
}
106+
throw e;
107+
}
95108
}
96109

97110
@Override
@@ -118,7 +131,19 @@ public final void addArgument(int argumentType) {
118131

119132
@Override
120133
public final void addArgument(int type, byte[] content) {
121-
addArgument(new ByteArrayArgument(type, parameterBufferMetaData.getByteArrayArgumentType(type), content));
134+
addArgument(createByteArrayArgument(type, content));
135+
}
136+
137+
private ByteArrayArgument createByteArrayArgument(int type, byte[] content) {
138+
try {
139+
return new ByteArrayArgument(type, parameterBufferMetaData.getByteArrayArgumentType(type), content);
140+
} catch (LengthOverflowException e) {
141+
if (tryUpgradeMetaData()) {
142+
// Do not inline parameterBufferMetaData or argument type; they might be different here than in the try
143+
return new ByteArrayArgument(type, parameterBufferMetaData.getByteArrayArgumentType(type), content);
144+
}
145+
throw e;
146+
}
122147
}
123148

124149
protected final void addArgument(Argument argument) {
@@ -216,6 +241,22 @@ public final boolean isEmpty() {
216241
return arguments.isEmpty();
217242
}
218243

244+
private boolean tryUpgradeMetaData() {
245+
if (!parameterBufferMetaData.isUpgradable()) return false;
246+
try {
247+
ParameterBufferMetaData newParameterBufferMetaData = parameterBufferMetaData.upgradeMetaData();
248+
List<Argument> newArguments = arguments.stream()
249+
.map(argument -> argument.transformTo(newParameterBufferMetaData))
250+
.toList();
251+
arguments.clear();
252+
arguments.addAll(newArguments);
253+
parameterBufferMetaData = newParameterBufferMetaData;
254+
return true;
255+
} catch (IllegalArgumentException e) {
256+
return false;
257+
}
258+
}
259+
219260
@Override
220261
@SuppressWarnings("java:S2097")
221262
public final boolean equals(@Nullable Object other) {

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

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText: Copyright 2015-2024 Mark Rotteveel
1+
// SPDX-FileCopyrightText: Copyright 2015-2026 Mark Rotteveel
22
// SPDX-License-Identifier: LGPL-2.1-or-later
33
package org.firebirdsql.gds.impl;
44

@@ -92,4 +92,31 @@ default ArgumentType getByteArgumentType(int tag) {
9292
return getIntegerArgumentType(tag);
9393
}
9494

95+
/**
96+
* Returns if this metadata type is upgradable.
97+
* <p>
98+
* The default implementation always returns {@code false}.
99+
* </p>
100+
*
101+
* @return {@code true} if this type is upgradable
102+
* @see #upgradeMetaData()
103+
* @since 7
104+
*/
105+
default boolean isUpgradable() {
106+
return false;
107+
}
108+
109+
/**
110+
* The parameter buffer metadata that can be upgraded to.
111+
* <p>
112+
* The default implementation always returns {@code this}.
113+
* </p>
114+
*
115+
* @return the upgrade buffer metadata, returns this instance if {@link #isUpgradable()} returns {@code false}
116+
* @since 7
117+
*/
118+
default ParameterBufferMetaData upgradeMetaData() {
119+
return this;
120+
}
121+
95122
}

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// SPDX-FileCopyrightText: Copyright 2003 Ryan Baldwin
22
// SPDX-FileCopyrightText: Copyright 2005 Roman Rokytskyy
3-
// SPDX-FileCopyrightText: Copyright 2014-2023 Mark Rotteveel
3+
// SPDX-FileCopyrightText: Copyright 2014-2026 Mark Rotteveel
44
// SPDX-License-Identifier: LGPL-2.1-or-later
55
package org.firebirdsql.gds.impl;
66

@@ -65,6 +65,16 @@ public ArgumentType getSingleArgumentType(int tag) {
6565
}
6666
return ArgumentType.TraditionalDpb;
6767
}
68+
69+
@Override
70+
public boolean isUpgradable() {
71+
return true;
72+
}
73+
74+
@Override
75+
public ParameterBufferMetaData upgradeMetaData() {
76+
return SPB_VERSION_3_ATTACH;
77+
}
6878
},
6979
// Technically this has nothing to do with SPB version 2/3
7080
SPB_VERSION_2(ISCConstants.isc_spb_current_version) {

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
SPDX-FileCopyrightText: Copyright 2003 Ryan Baldwin
33
SPDX-FileCopyrightText: Copyright 2003-2005 Roman Rokytskyy
44
SPDX-FileCopyrightText: Copyright 2004 Gabriel Reid
5-
SPDX-FileCopyrightText: Copyright 2012-2023 Mark Rotteveel
5+
SPDX-FileCopyrightText: Copyright 2012-2026 Mark Rotteveel
66
SPDX-License-Identifier: LGPL-2.1-or-later
77
*/
88
package org.firebirdsql.gds.impl.argument;
99

1010
import org.firebirdsql.gds.Parameter;
11+
import org.firebirdsql.gds.impl.ParameterBufferMetaData;
1112

1213
import java.io.IOException;
1314
import java.io.OutputStream;
@@ -76,4 +77,17 @@ public long getValueAsLong() {
7677
*/
7778
public abstract int getLength();
7879

80+
/**
81+
* If needed, returns a new argument to transform to a suitable argument type, otherwise returns this instance.
82+
*
83+
* @param parameterBufferMetaData
84+
* parameter buffer metadata (used to determine the needed argument type)
85+
* @return either a new argument if transformation is needed, or this instance
86+
* @throws IllegalArgumentException
87+
* if transformation is needed, but the creation of the new instance fails (e.g. downgrading from
88+
* {@link ArgumentType#Wide} to {@link ArgumentType#TraditionalDpb}, and the value is too long)
89+
* @since 7
90+
*/
91+
public abstract Argument transformTo(ParameterBufferMetaData parameterBufferMetaData);
92+
7993
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.firebirdsql.encodings.Encoding;
1111
import org.firebirdsql.gds.ParameterBuffer;
1212
import org.firebirdsql.gds.VaxEncoding;
13+
import org.firebirdsql.gds.impl.ParameterBufferMetaData;
1314
import org.jspecify.annotations.Nullable;
1415

1516
import java.io.IOException;
@@ -72,6 +73,13 @@ public void copyTo(ParameterBuffer buffer, @Nullable Encoding encoding) {
7273
buffer.addArgument(getType(), value);
7374
}
7475

76+
@Override
77+
public BigIntArgument transformTo(ParameterBufferMetaData parameterBufferMetaData) {
78+
ArgumentType newArgumentType = parameterBufferMetaData.getIntegerArgumentType(getType());
79+
if (newArgumentType == argumentType) return this;
80+
return new BigIntArgument(getType(), newArgumentType, value);
81+
}
82+
7583
@Override
7684
public boolean equals(@Nullable Object other) {
7785
if (this == other) return true;

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

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

1010
import org.firebirdsql.encodings.Encoding;
1111
import org.firebirdsql.gds.ParameterBuffer;
12+
import org.firebirdsql.gds.impl.ParameterBufferMetaData;
1213
import org.jspecify.annotations.Nullable;
1314

1415
import java.io.IOException;
@@ -69,6 +70,13 @@ public void copyTo(ParameterBuffer buffer, @Nullable Encoding encoding) {
6970
buffer.addArgument(getType(), value);
7071
}
7172

73+
@Override
74+
public ByteArgument transformTo(ParameterBufferMetaData parameterBufferMetaData) {
75+
ArgumentType newArgumentType = parameterBufferMetaData.getByteArgumentType(getType());
76+
if (newArgumentType == argumentType) return this;
77+
return new ByteArgument(getType(), newArgumentType, value);
78+
}
79+
7280
@Override
7381
public boolean equals(@Nullable Object other) {
7482
if (this == other) return true;

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

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

1111
import org.firebirdsql.encodings.Encoding;
1212
import org.firebirdsql.gds.ParameterBuffer;
13+
import org.firebirdsql.gds.impl.ParameterBufferMetaData;
1314
import org.jspecify.annotations.Nullable;
1415

1516
import java.io.IOException;
@@ -37,20 +38,26 @@ public final class ByteArrayArgument extends TypedArgument {
3738
private final byte[] value;
3839

3940
/**
40-
* Initializes an instance of ByteArrayArgument.
41+
* Initialises an instance of ByteArrayArgument.
4142
*
4243
* @param type
43-
* Parameter type
44+
* parameter type
45+
* @param argumentType
46+
* argument type
4447
* @param value
45-
* Byte array with a maximum length defined by {@code argumentType}.
48+
* byte array
49+
* @throws IllegalArgumentException
50+
* if {@code type} is not valid for byte arrays, or if {@code value} is {@code null}
51+
* @throws LengthOverflowException
52+
* if the length of {@code value} exceeds {@link ArgumentType#getMaxLength()}
4653
*/
4754
public ByteArrayArgument(int type, ArgumentType argumentType, byte[] value) {
4855
super(type, checkArgumentType(argumentType, SUPPORTED_ARGUMENT_TYPES));
4956
if (value == null) {
5057
throw new IllegalArgumentException("byte array value should not be null");
5158
}
5259
if (value.length > argumentType.getMaxLength()) {
53-
throw new IllegalArgumentException(
60+
throw new LengthOverflowException(
5461
String.format("byte array value should not be longer than %d bytes, length was %d",
5562
argumentType.getMaxLength(), value.length));
5663
}
@@ -78,11 +85,23 @@ public int getValueAsInt() {
7885
}
7986
}
8087

88+
// primarily intended for testing purposes
89+
public byte[] getValueAsBytes() {
90+
return value.clone();
91+
}
92+
8193
@Override
8294
public void copyTo(ParameterBuffer buffer, @Nullable Encoding encoding) {
8395
buffer.addArgument(getType(), value.clone());
8496
}
8597

98+
@Override
99+
public ByteArrayArgument transformTo(ParameterBufferMetaData parameterBufferMetaData) {
100+
ArgumentType newArgumentType = parameterBufferMetaData.getByteArrayArgumentType(getType());
101+
if (newArgumentType == argumentType) return this;
102+
return new ByteArrayArgument(getType(), newArgumentType, value);
103+
}
104+
86105
@Override
87106
public boolean equals(@Nullable Object other) {
88107
if (this == other) return true;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
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+
import java.io.Serial;
6+
7+
/**
8+
* Thrown by {@link StringArgument} and {@link ByteArrayArgument} if a value's length exceeds that of their
9+
* {@link ArgumentType}.
10+
*
11+
* @since 7
12+
*/
13+
public class LengthOverflowException extends IllegalArgumentException {
14+
15+
@Serial
16+
private static final long serialVersionUID = 5735116134576091931L;
17+
18+
LengthOverflowException(String message) {
19+
super(message);
20+
}
21+
22+
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.firebirdsql.encodings.Encoding;
1111
import org.firebirdsql.gds.ParameterBuffer;
1212
import org.firebirdsql.gds.VaxEncoding;
13+
import org.firebirdsql.gds.impl.ParameterBufferMetaData;
1314
import org.jspecify.annotations.Nullable;
1415

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

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

0 commit comments

Comments
 (0)