Data: Check key order when parsing RI mappings and fail-fast if out-of-order

before the signature check
This commit is contained in:
zzz
2025-02-07 12:18:52 -05:00
parent 327c8c69ef
commit 6cef4ccbb1
3 changed files with 33 additions and 3 deletions

View File

@ -134,7 +134,8 @@ public class DataHelper {
* is repeated until there are no more bytes (not characters!) left as defined by the
* first two byte integer.
*
* As of 0.9.18, throws DataFormatException on duplicate key
* As of 0.9.18, throws DataFormatException on duplicate key
* Does NOT enforce key ordering.
*
* @param rawStream stream to read the mapping from
* @throws DataFormatException if the format is invalid
@ -152,6 +153,7 @@ public class DataHelper {
* Ditto, load into an existing properties
*
* As of 0.9.18, throws DataFormatException on duplicate key
* Does NOT enforce key ordering.
*
* @param props The Properties to load into.
* As of 0.9.38, if null, a new OrderedProperties will be created.
@ -163,6 +165,26 @@ public class DataHelper {
* @since 0.8.13
*/
public static Properties readProperties(InputStream rawStream, Properties props)
throws DataFormatException, IOException {
return readProperties(rawStream, props, false);
}
/**
* Ditto, load into an existing properties
*
* As of 0.9.18, throws DataFormatException on duplicate key
*
* @param props The Properties to load into.
* As of 0.9.38, if null, a new OrderedProperties will be created.
* @param rawStream stream to read the mapping from
* @param enforceOrder if true, throw DataFormatException if keys are not ordered
* @throws DataFormatException if the format is invalid
* @throws IOException if there is a problem reading the data
* @return the parameter props, or (as of 0.9.38) a new OrderedProperties if props is null,
* and an immutable EmptyProperties if empty.
* @since 0.9.66
*/
public static Properties readProperties(InputStream rawStream, Properties props, boolean enforceOrder)
throws DataFormatException, IOException {
int size = (int) readLong(rawStream, 2);
if (size == 0) {
@ -174,11 +196,15 @@ public class DataHelper {
// full read guaranteed
read(rawStream, data);
ByteArrayInputStream in = new ByteArrayInputStream(data);
String prev = "";
while (in.available() > 0) {
String key = readString(in);
String cached = _propertiesKeyCache.get(key);
if (cached != null)
key = cached;
if (enforceOrder && key.compareTo(prev) <= 0)
throw new DataFormatException("option " + key + " out of order");
prev = key;
int b = in.read();
if (b != '=')
throw new DataFormatException("Bad key");

View File

@ -292,7 +292,9 @@ public class RouterAddress extends DataStructureImpl {
_transportStyle = "NTCP";
else if (_transportStyle.equals("SSU2"))
_transportStyle = "SSU2";
DataHelper.readProperties(in, _options);
// enforce mapping order so bad ones will fail-fast
// before the signature check
DataHelper.readProperties(in, _options, true);
}
/**

View File

@ -606,7 +606,9 @@ public class RouterInfo extends DatabaseEntry {
_peers.add(peerIdentityHash);
}
}
DataHelper.readProperties(din, _options);
// enforce mapping order so bad ones will fail-fast
// before the signature check
DataHelper.readProperties(din, _options, true);
_signature = new Signature(type);
_signature.readBytes(in);