make sure no invalid keys pass into dicts

This commit is contained in:
mykola2312 2024-10-17 08:22:46 +03:00
parent 679670b468
commit c978925f70
5 changed files with 60 additions and 4 deletions

View file

@ -1,5 +1,6 @@
package com.mykola2312.retracker.bencode;
import com.mykola2312.retracker.bencode.error.BErrorInvalidKey;
import com.mykola2312.retracker.bencode.error.BErrorKeyNotFound;
import com.mykola2312.retracker.bencode.error.BErrorNoChildren;
import com.mykola2312.retracker.bencode.error.BErrorValueCast;
@ -11,7 +12,20 @@ public class BDict extends BList {
return BType.DICT;
}
public BDict set(BValue key, BValue value) {
public BDict set(BValue key, BValue value) throws BErrorInvalidKey {
if (key == null || value == null) {
throw new BErrorInvalidKey(this, key, "key or value is null");
}
/* key type cannot have child, because it messes up tree,
* in other words, key cannot be a list or dict
*/
if (key.getChild() != null) {
throw new BErrorInvalidKey(this, key, "key has child, because its list or a dict");
}
if (key.getType().equals(BType.LIST) || key.getType().equals(BType.DICT)) {
throw new BErrorInvalidKey(this, key, "key shall not be list or a dict");
}
BValue node = find(key);
if (node != null) {
node.setNext(value);
@ -24,7 +38,14 @@ public class BDict extends BList {
}
public BDict set(String key, BValue value) {
return set(new BString(key), value);
/* we "suppress" here exceptions since this method is used
* for building BTrees, not when decoding
*/
try {
return set(new BString(key), value);
} catch (BErrorInvalidKey e) {
throw new RuntimeException("this shouldn't have happened in BDict set: " + e.getMessage());
}
}
/* since we're going to employ builder pattern, we can't return null.

View file

@ -1,12 +1,14 @@
package com.mykola2312.retracker.bencode;
import static io.netty.buffer.Unpooled.buffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import com.mykola2312.retracker.bencode.error.BDecodeError;
import com.mykola2312.retracker.bencode.error.BDecodeMalformed;
import com.mykola2312.retracker.bencode.error.BDecodeParseError;
import com.mykola2312.retracker.bencode.error.BErrorInvalidKey;
import com.mykola2312.retracker.bencode.error.BErrorNoRoot;
import com.mykola2312.retracker.bencode.error.BErrorValueCast;
@ -102,7 +104,11 @@ public class BTree {
while (offset < data.length && data[offset] != BTree.BE_END) {
BValue key = decode();
BValue value = decode();
dict.set(key, value);
try {
dict.set(key, value);
} catch (BErrorInvalidKey e) {
throw new BDecodeMalformed(data, offset, e.getMessage());
}
}
// advance past terminator
offset++;
@ -171,6 +177,7 @@ public class BTree {
case LIST:
buffer.writeByte(BE_LIST);
for (BValue item : node) {
System.err.println("encoding list item: " + item);
encode(item);
}
buffer.writeByte(BE_END);

View file

@ -0,0 +1,11 @@
package com.mykola2312.retracker.bencode.error;
import com.mykola2312.retracker.bencode.BValue;
public class BErrorInvalidKey extends BValueError {
private static final long serialVersionUID = 8821935501326704941L;
public BErrorInvalidKey(BValue node, BValue key, String message) {
super(node, String.format("key \"%s\" invalid: %s", key, message));
}
}

View file

@ -8,6 +8,7 @@ import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import org.junit.jupiter.api.Test;
import com.mykola2312.retracker.bencode.error.BErrorInvalidKey;
import com.mykola2312.retracker.bencode.error.BErrorKeyNotFound;
import com.mykola2312.retracker.bencode.error.BErrorValueCast;
import com.mykola2312.retracker.bencode.error.BValueError;
@ -37,7 +38,7 @@ public class BDictTest {
}
@Test
public void testKeyChild() {
public void testKeyChild() throws BErrorInvalidKey {
BDict dict = new BDict();
dict.set(new BInteger(1), new BInteger(2));

View file

@ -7,6 +7,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
@ -15,6 +16,7 @@ import org.junit.jupiter.api.Test;
import com.mykola2312.retracker.bencode.error.BDecodeError;
import com.mykola2312.retracker.bencode.error.BDecodeMalformed;
import com.mykola2312.retracker.bencode.error.BError;
import com.mykola2312.retracker.bencode.error.BErrorInvalidKey;
public class BTreeTest {
@Test
@ -141,6 +143,17 @@ public class BTreeTest {
});
}
@Test
public void testInvalidKeys() {
assertThrows(BErrorInvalidKey.class, () -> {
new BTree().setRoot(new BDict()).set(new BList(), new BList());
});
assertThrows(BDecodeMalformed.class, () -> {
new BTree().decode("dlelee".getBytes());
});
}
@Test
public void testEncode() {
assertDoesNotThrow(() -> {
@ -148,6 +161,9 @@ public class BTreeTest {
tree.setRoot(new BInteger(1));
assertArrayEquals("i1e".getBytes(), tree.encode());
tree.setRoot(new BString("test"));
assertArrayEquals("4:test".getBytes(), tree.encode());
});
}