Ask Your Question
0

getting zero length range from end of buffer

asked 2025-02-10 05:28:46 +0000

gfim gravatar image

updated 2025-02-10 09:20:23 +0000

grahamb gravatar image

I'm writing a custom dissector for a home-grown protocol. Strings in the protocol are encoded as a binary 4-byte byte-count followed by the bytes of the string. Zero length strings are allowable. The problem occurs when a zero length string is the very last object in the buffer.

I have a function getString():

function getString(buffer, position)
    local length = buffer:range(position, 4):uint()
    position = position + 4
    local string = buffer:range(position, length)
    position = position + length
    return position, string
end

If I call that with a buffer (in hex):

00 00 00 03 41 42 43 00 00 00 00

I correctly get the string "ABC" in the TvbRange that's returned, and position is correctly returned as 7.

If I call it with a buffer:

00 00 00 00 00 00 00 00

I correctly get an empty TvbRange returned, and position is correctly returned as 4.

But, if I call it with a buffer:

00 00 00 00

I get a runtime error "Range is out of bounds".

Is there some way to get range() to correctly return an empty range in this case? Can I test for the condition (e.g. length == 0 and position == buffer:len()) and return a "fake" TvbRange.

Currently, I'm returning string as nil. But that means that I have to test for nil everywhere that getString() is called - that's inconvenient.

Thanks for any help, Graham

edit retag flag offensive close merge delete

Comments

Why not return the range that was passed in and set position = nil or -1 to indicate no more buffer to process?

Chuckc gravatar imageChuckc ( 2025-02-10 14:17:47 +0000 )edit

Something like so?

function getString(buffer, position)
    local length = buffer:range(position, 4):uint()
    position = position + 4

    if length > 0 then
        local string = buffer:range(position, length)
        position = position + length
        return position, string
    end

    return position, nil

end
cmaynard gravatar imagecmaynard ( 2025-02-10 19:32:54 +0000 )edit

Thanks for responding Chuckc and cmaynard.

Yes, I can do that. But, as I said, it's not very convenient. I'd like to be able to do:

pos = 0
pos, str = getString(buffer, pos)
subtree:add(pf_from, str)
pos, str = getString(buffer, pos)
subtree:add(pf_to, str)
...

But, if I need to check for str being nil every time, it's not as simple.

Now that I think about it, is this really a Lua bug? Should I not be able to get a zero length TvbRange from the end of a Tvb. In other words, perhaps buffer:range(buffer:len(), 0) should not generate an error.

Thanks again, Graham.

gfim gravatar imagegfim ( 2025-02-10 20:04:03 +0000 )edit

My current workaround is:

function getString(buffer, position)
    local length = buffer:range(position, 4):uint()
    position = position + 4

    -- this is a workaround for a "Range is out of bounds" error with a zero length string at the very end of the buffer
    -- it should be just: local string = buffer:range(position, length)
    local pos = position
    if length == 0 and pos == buffer:len() then
        pos = pos - 1
    end
    local string = buffer:range(pos, length)

    local string = buffer:range(position, length)
    position = position + length
    return position, string
end

It's not correct, but it's close enough.

gfim gravatar imagegfim ( 2025-02-10 20:20:57 +0000 )edit

1 Answer

Sort by ยป oldest newest most voted
0

answered 2025-02-10 23:01:47 +0000

Chuckc gravatar image

This is similar to 15655: Lua TvbRanges do not support truncated captures where tvb_captured_length < tvb_reported_length.

The getString function is failing here (epan/wslua/wslua_tvb.c):

    if (offset >= tvbr->len || (len + offset) > tvbr->len) {
        luaL_error(L,"Range is out of bounds");
        return 0;
    }

offset = 4 and tvbr->len = 4 so fails on offset >= tvbr->len.
A zero (0) length tvb (len = 0) is ok but the code does not allow asking for those 0 octets outside the source tvb.

edit flag offensive delete link more

Comments

Thanks again, Chuckc.

Yes, that's what I expected to code to look like. I think that if should be changed to just:

if ((len + offset) > tvbr->len) {

Graham

gfim gravatar imagegfim ( 2025-02-10 23:07:55 +0000 )edit

I added a comment to the open issue linking back to this question.
The comparison code is from the original commit: 08797664.

Chuckc gravatar imageChuckc ( 2025-02-10 23:19:29 +0000 )edit

Not a complete expert on the Lua code, but I think there should probably be some checks for negative len too, but then again possibly that's handled by it calling push_TvbRange? Looking at the other functions in lua_tvb.c, it sees that they vary on whether negative lengths are completely disallowed, -1 means "to the end" but other negative lengths are disallowed, or "any negative length means to the end (?!)"

johnthacker gravatar imagejohnthacker ( 2025-02-11 01:11:27 +0000 )edit

The offset > tvbr->len part of the check is to deal with negative lengths being passed in, I think.

johnthacker gravatar imagejohnthacker ( 2025-02-18 15:08:02 +0000 )edit

https://gitlab.com/wireshark/wireshar... shoud help with it, though I'm not sure that will be backported, so it may not be until 5.0 that it is possible.

johnthacker gravatar imagejohnthacker ( 2025-02-19 11:56:07 +0000 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 2025-02-10 05:28:46 +0000

Seen: 72 times

Last updated: Feb 10