Skip to content

Commit 3dc5a7a

Browse files
committed
Fix method so it allows necessary padding
1 parent bc273d1 commit 3dc5a7a

File tree

2 files changed

+31
-8
lines changed

2 files changed

+31
-8
lines changed

src/main/java/co/rsk/bitcoinj/script/ScriptChunk.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -183,18 +183,22 @@ private int decodePositiveNConsideringEncoding() {
183183
throw new IllegalArgumentException("Chunk has null data.");
184184
}
185185
int dataLength = data.length;
186-
byte moreSignificantByte = data[dataLength - 1];
186+
byte mostSignificantByte = data[dataLength - 1];
187187

188-
if (moreSignificantByte == 0x00) {
189-
throw new IllegalArgumentException("Number from chunk does not have minimal encoding.");
190-
}
191-
192-
int signByte = moreSignificantByte & 0x80;
188+
int signByte = mostSignificantByte & 0x80;
193189
boolean isPositive = signByte == 0;
194190
if (!isPositive) {
195191
throw new IllegalArgumentException("Number from chunk is not positive.");
196192
}
197193

194+
boolean hasPadding = mostSignificantByte == 0;
195+
if (hasPadding) {
196+
boolean shouldAllowPadding = (data[dataLength - 2] & 0x80) != 0;
197+
if (!shouldAllowPadding) {
198+
throw new IllegalArgumentException("Number from chunk does not have minimal encoding.");
199+
}
200+
}
201+
198202
if (dataLength > 4) {
199203
throw new IllegalArgumentException("Number from chunk has more than 4 bytes.");
200204
}

src/test/java/co/rsk/bitcoinj/script/ScriptChunkTest.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,10 @@ public void decodePositiveN_forZero_throwsIAE() {
180180
@Test
181181
public void decodePositiveN_forNumberWithoutMinimalEncoding_throwsIAE() {
182182
byte zero = 0x00;
183-
for (int n=0; n<20; n++) {
184-
int i = (1 << n); // i = (2^n)
183+
184+
// from 1 to 15, numbers are small numbers and therefore pushed as opcodes
185+
// with null chunk data
186+
for (int i=1; i<16; i++) {
185187
byte[] numWithoutMinimalEncoding = new byte[] {(byte) i, zero};
186188

187189
ScriptBuilder builder = new ScriptBuilder();
@@ -192,6 +194,23 @@ public void decodePositiveN_forNumberWithoutMinimalEncoding_throwsIAE() {
192194
assertFalse(chunk.isPositiveN());
193195
assertThrows(IllegalArgumentException.class, chunk::decodePositiveN);
194196
}
197+
198+
for (int n=4; n<20; n++) {
199+
int i = (1 << n); // i = (2^n)
200+
ScriptBuilder builder = new ScriptBuilder();
201+
ScriptChunk chunk = builder.number(i).build().getChunks().get(0);
202+
byte[] chunkData = chunk.data;
203+
204+
// add zero padding so the number does not have minimal encoding
205+
byte [] numWithoutMinimalEncoding = Arrays.copyOf(chunkData, chunkData.length + 1);
206+
numWithoutMinimalEncoding[chunkData.length] = zero;
207+
208+
// build the chunk for the number without minimal encoding
209+
builder = new ScriptBuilder();
210+
ScriptChunk newChunk = builder.data(numWithoutMinimalEncoding).build().chunks.get(0);
211+
assertFalse(newChunk.isPositiveN());
212+
assertThrows(IllegalArgumentException.class, newChunk::decodePositiveN);
213+
}
195214
}
196215

197216
@Test

0 commit comments

Comments
 (0)