Open milcode opened 2 years ago
i fixed this bug, you can copy the code in class BerTlvParser, find function "parseWithResult" and "addChildren",add params "resultLevel":
private ParseResult parseWithResult(int resultLevel,int aLevel, byte[] aBuf, int aOffset, int aLen) {
String levelPadding = createLevelPadding(aLevel);
if(aOffset+aLen > aBuf.length) {
throw new IllegalStateException("Length is out of the range [offset="+aOffset+", len="+aLen+", array.length="+aBuf.length+", level="+aLevel+"]");
}
if(log.isDebugEnabled()) {
log.debug("{}parseWithResult(level={}, offset={}, len={}, buf={})", levelPadding, aLevel, aOffset, aLen, HexUtil.toFormattedHexString(aBuf, aOffset, aLen));
}
// tag
int tagBytesCount = getTagBytesCount(aBuf, aOffset);
BerTag tag = createTag(levelPadding, aBuf, aOffset, tagBytesCount);
if(log.isDebugEnabled()) {
log.debug("{}tag = {}, tagBytesCount={}, tagBuf={}", levelPadding, tag, tagBytesCount, HexUtil.toFormattedHexString(aBuf, aOffset, tagBytesCount));
}
// length
int lengthBytesCount = getLengthBytesCount(aBuf, aOffset + tagBytesCount);
int valueLength = getDataLength(aBuf, aOffset + tagBytesCount);
if(log.isDebugEnabled()) {
log.debug("{}lenBytesCount = {}, len = {}, lenBuf = {}"
, levelPadding, lengthBytesCount, valueLength, HexUtil.toFormattedHexString(aBuf, aOffset + tagBytesCount, lengthBytesCount));
}
// value
if(tag.isConstructed() && resultLevel > aLevel) {
ArrayList<BerTlv> list = new ArrayList<BerTlv>();
addChildren(resultLevel,aLevel, aBuf, aOffset + tagBytesCount + lengthBytesCount, levelPadding, lengthBytesCount, valueLength, list);
int resultOffset = aOffset + tagBytesCount + lengthBytesCount + valueLength;
if(log.isDebugEnabled()) {
log.debug("{}returning constructed offset = {}", levelPadding, resultOffset);
}
return new ParseResult(new BerTlv(tag, list), resultOffset);
} else {
// value
byte[] value = new byte[valueLength];
System.arraycopy(aBuf, aOffset+tagBytesCount+lengthBytesCount, value, 0, valueLength);
int resultOffset = aOffset + tagBytesCount + lengthBytesCount + valueLength;
if(log.isDebugEnabled()) {
log.debug("{}value = {}", levelPadding, HexUtil.toFormattedHexString(value));
log.debug("{}returning primitive offset = {}", levelPadding, resultOffset);
}
return new ParseResult(new BerTlv(tag, value), resultOffset);
}
}
private void addChildren(int resultLevel,int aLevel, byte[] aBuf, int aOffset, String levelPadding, int aDataBytesCount, int valueLength, ArrayList<BerTlv> list) {
int startPosition = aOffset;
int len = valueLength;
while (startPosition < aOffset + valueLength ) {
ParseResult result = parseWithResult(resultLevel,aLevel+1, aBuf, startPosition, len);
list.add(result.tlv);
startPosition = result.offset;
len = (aOffset + valueLength) - startPosition;
if(log.isDebugEnabled()) {
log.debug("{}level {}: adding {} with offset {}, startPosition={}, aDataBytesCount={}, valueLength={}"
, levelPadding, aLevel, result.tlv.getTag(), result.offset, startPosition, aDataBytesCount, valueLength);
}
}
}
Then edit "parse" function:
public BerTlvs parse(int resultLevel, byte[] aBuf) {
return parse(resultLevel, aBuf, 0, aBuf.length);
}
call it (i use it in kotlin):
val data = "62 19\n" +
"82 02 4121\n" +
"83 02 2F05\n" +
"A5 03 800161\n" +
"8A 01 05\n" +
"8B 03 2F0605\n" +
"80 02 000A"
val data2 = data.replace("\n","").replace(" ","")
val parse = BerTlvParser().parse(1,HexUtil.parseHex(data2)).find(BerTag(0x62))
println( parse.bytesValue)
this is result:
when your call it: BerTlvParser().parse(0,HexUtil.parseHex(data2)).find(BerTag(0x62)) result is:
Current BerTlv find is searching for the TAG recursively and sometimes ends up returns incorrect values.
Example:
If I have the following data and want to find the BerTLV 0x80 under 0x62, it will return the 0x80 inside 0xA5.
62 19 82 02 4121 83 02 2F05 A5 03 800161 8A 01 05 8B 03 2F0605 80 02 000A
One option would be to create a findOnChildBerTlv, to limit the search to a 1 level depth. Adding a new parameter maxDepth would be another solution.