Skip to content

Commit

Permalink
Fix parsing of empty labels and messages, and parsing of labels and m…
Browse files Browse the repository at this point in the history
…essages with an unescaped equals sign in their value.
  • Loading branch information
schildbach authored and mikehearn committed Apr 22, 2014
1 parent b3162cb commit b0fa543
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 53 deletions.
21 changes: 12 additions & 9 deletions core/src/main/java/com/google/bitcoin/uri/BitcoinURI.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012 the original author or authors.
* Copyright 2012, 2014 the original author or authors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -32,6 +32,7 @@
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;

import static com.google.common.base.Preconditions.checkNotNull;
Expand Down Expand Up @@ -192,14 +193,15 @@ public BitcoinURI(@Nullable NetworkParameters params, String input) throws Bitco
private void parseParameters(@Nullable NetworkParameters params, String addressToken, String[] nameValuePairTokens) throws BitcoinURIParseException {
// Attempt to decode the rest of the tokens into a parameter map.
for (String nameValuePairToken : nameValuePairTokens) {
String[] tokens = nameValuePairToken.split("=");
if (tokens.length != 2 || "".equals(tokens[0])) {
throw new BitcoinURIParseException("Malformed Bitcoin URI - cannot parse name value pair '" +
final int sepIndex = nameValuePairToken.indexOf('=');
if (sepIndex == -1)
throw new BitcoinURIParseException("Malformed Bitcoin URI - no separator in '" +
nameValuePairToken + "'");
}

String nameToken = tokens[0].toLowerCase();
String valueToken = tokens[1];
if (sepIndex == 0)
throw new BitcoinURIParseException("Malformed Bitcoin URI - empty name '" +
nameValuePairToken + "'");
final String nameToken = nameValuePairToken.substring(0, sepIndex).toLowerCase(Locale.ENGLISH);
final String valueToken = nameValuePairToken.substring(sepIndex + 1);

// Parse the amount.
if (FIELD_AMOUNT.equals(nameToken)) {
Expand All @@ -219,7 +221,8 @@ private void parseParameters(@Nullable NetworkParameters params, String addressT
} else {
// Known fields and unknown parameters that are optional.
try {
putWithValidation(nameToken, URLDecoder.decode(valueToken, "UTF-8"));
if (valueToken.length() > 0)
putWithValidation(nameToken, URLDecoder.decode(valueToken, "UTF-8"));
} catch (UnsupportedEncodingException e) {
// Unreachable.
throw new RuntimeException(e);
Expand Down
55 changes: 11 additions & 44 deletions core/src/test/java/com/google/bitcoin/uri/BitcoinURITest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012 the original author or authors.
* Copyright 2012, 2014 the original author or authors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -271,38 +271,16 @@ public void testBad_Amount() throws BitcoinURIParseException {
}
}

/**
* Handles a badly formatted label field
*
* @throws BitcoinURIParseException
* If something goes wrong
*/
@Test
public void testBad_Label() throws BitcoinURIParseException {
try {
testObject = new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS
+ "?label=");
fail("Expecting BitcoinURIParseException");
} catch (BitcoinURIParseException e) {
assertTrue(e.getMessage().contains("label"));
}
public void testEmpty_Label() throws BitcoinURIParseException {
assertNull(new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS
+ "?label=").getLabel());
}

/**
* Handles a badly formatted message field
*
* @throws BitcoinURIParseException
* If something goes wrong
*/
@Test
public void testBad_Message() throws BitcoinURIParseException {
try {
testObject = new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS
+ "?message=");
fail("Expecting BitcoinURIParseException");
} catch (BitcoinURIParseException e) {
assertTrue(e.getMessage().contains("message"));
}
public void testEmpty_Message() throws BitcoinURIParseException {
assertNull(new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS
+ "?message=").getMessage());
}

/**
Expand All @@ -322,21 +300,10 @@ public void testBad_Duplicated() throws BitcoinURIParseException {
}
}

/**
* Handles case when there are too many equals
*
* @throws BitcoinURIParseException
* If something goes wrong
*/
@Test
public void testBad_TooManyEquals() throws BitcoinURIParseException {
try {
testObject = new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS
+ "?label=aardvark=zebra");
fail("Expecting BitcoinURIParseException");
} catch (BitcoinURIParseException e) {
assertTrue(e.getMessage().contains("cannot parse name value pair"));
}
public void testGood_ManyEquals() throws BitcoinURIParseException {
assertEquals("aardvark=zebra", new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":"
+ MAINNET_GOOD_ADDRESS + "?label=aardvark=zebra").getLabel());
}

/**
Expand Down Expand Up @@ -377,7 +344,7 @@ public void testUnknown() throws BitcoinURIParseException {
+ "?aardvark");
fail("Expecting BitcoinURIParseException");
} catch (BitcoinURIParseException e) {
assertTrue(e.getMessage().contains("cannot parse name value pair"));
assertTrue(e.getMessage().contains("no separator"));
}

// Unknown and required field
Expand Down

0 comments on commit b0fa543

Please sign in to comment.