RIOT-OS / RIOT

RIOT - The friendly OS for IoT
https://riot-os.org
GNU Lesser General Public License v2.1
4.86k stars 1.97k forks source link

gcoap_fileserver: can't deal with 16 byte block size #20686

Open benpicco opened 3 months ago

benpicco commented 3 months ago

Description

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

Steps to reproduce the issue

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

fabian18 commented 3 months ago

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.

benpicco commented 3 months ago

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.