Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Limite depth on BerTlv find #22

Open
milcode opened this issue Jan 6, 2022 · 1 comment
Open

Limite depth on BerTlv find #22

milcode opened this issue Jan 6, 2022 · 1 comment

Comments

@milcode
Copy link

milcode commented Jan 6, 2022

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.

@milcode milcode changed the title Limite depth on findTlv Limite depth on BerTlv find Jan 6, 2022
@ChenShayZeak
Copy link

ChenShayZeak commented Oct 13, 2022

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:
image

when your call it:
BerTlvParser().parse(0,HexUtil.parseHex(data2)).find(BerTag(0x62))
result is:
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants