RIOT icon indicating copy to clipboard operation
RIOT copied to clipboard

gcoap_fileserver: can't deal with 16 byte block size

Open benpicco opened this issue 1 year ago • 2 comments

Description

When requesting 16 byte block size, the server will respond with an invalid packet.

Steps to reproduce the issue

  • run examples/gcoap_fileserver:

    make -C examples/gcoap_fileserver PORT=tap1 all term
    
  • create a dummy file

    echo "Hello World!" > examples/gcoap_fileserver/native/me
    
  • Try to access the file via e.g. ncget with a 16 byte block size

     CFLAGS=-DCONFIG_NANOCOAP_BLOCKSIZE_DEFAULT=COAP_BLOCKSIZE_16 make -C tests/net/nanocoap_cli all term
     > ncget coap://[fe80::d07c:7cff:fe6d:9441]/vfs/me -
    

Expected results

We get the response in a single block

Actual results

We get the response in a single block, but there is some garbage after the block2 option:

Wireshark Output

gcoap_fileserver.pcapng.gz

Versions

RIOT master

benpicco avatar May 22 '24 18:05 benpicco

Screenshot from 2024-05-22 21-54-49

It happens because first we assume more=true --> [block num 0, more 1, szx 0]. It is encoded as 3 bytes 0xd1, 0x06, 0x08. Meaning delta 13 + 6 , length 1. Now when we correct the more flag in coap_block_finish() the option value becomes 0. The encoded option value unsigned integer 0 has length 0. That means 0xd1 in the previous encoding becomes 0xd0. The byte sequence left in the packed buffer becomes 0xd0, 0x06, 0x08. This decodes as the correct block option and the 0x08which is a leftover of the first encoding.

The issue is that an option written to a buffer is rewritten with a smaller option length, because the option value bacame actually 0.

fabian18 avatar May 22 '24 20:05 fabian18

Thank you, that explanation makes perfect sense! So the (long) option gets first written by coap_opt_add_block2(), then it is overwritten later by coap_block2_finish() with a shorter option, leaving two garbage bytes before the next option starts.

benpicco avatar May 22 '24 22:05 benpicco