mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-25 17:59:25 +01:00
wscutil: Allow 0-length attributes in wsc_attr_builder
wsc_attr_builder_start_attr and wsc_attr_builder_free look at builder->curlen to see whether the TLV's length needs to be updated to include the previous attribute. If builder->curlen is 0 wsc_attr_builder_start_attr assumes there's no previous attribute and starts writing at current builder->offset. If the previous attribute length was 0 curlen would stay at 0 and that attribute would get overwritten with the new one. To solve this add the 4 bytes of the T and L to curlen as soon as a new attribute is started, and subtract them when writing the L value. The alternative would be to set a flag to say whether an attribute was started. The spec explicitly allows 0-length attributes in section 12: "The variable length string attributes, e.g., Device Name, are encoded without null-termination, i.e., no 0x00 octets added to the end of the value. If the string is empty, the attribute length is set to zero."
This commit is contained in:
parent
8840d4623d
commit
8173ded0eb
@ -1634,11 +1634,12 @@ static bool wsc_attr_builder_start_attr(struct wsc_attr_builder *builder,
|
|||||||
/* Record previous attribute's length */
|
/* Record previous attribute's length */
|
||||||
if (builder->curlen > 0) {
|
if (builder->curlen > 0) {
|
||||||
bytes = builder->buf + builder->offset;
|
bytes = builder->buf + builder->offset;
|
||||||
l_put_be16(builder->curlen, bytes + 2);
|
l_put_be16(builder->curlen - 4, bytes + 2);
|
||||||
builder->offset += 4 + builder->curlen;
|
builder->offset += builder->curlen;
|
||||||
builder->curlen = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
builder->curlen = 4;
|
||||||
|
|
||||||
if (builder->offset + 4 >= builder->capacity)
|
if (builder->offset + 4 >= builder->capacity)
|
||||||
wsc_attr_builder_grow(builder);
|
wsc_attr_builder_grow(builder);
|
||||||
|
|
||||||
@ -1650,10 +1651,10 @@ static bool wsc_attr_builder_start_attr(struct wsc_attr_builder *builder,
|
|||||||
|
|
||||||
static bool wsc_attr_builder_put_u8(struct wsc_attr_builder *builder, uint8_t v)
|
static bool wsc_attr_builder_put_u8(struct wsc_attr_builder *builder, uint8_t v)
|
||||||
{
|
{
|
||||||
if (builder->offset + 4 + builder->curlen + 1 >= builder->capacity)
|
if (builder->offset + builder->curlen + 1 >= builder->capacity)
|
||||||
wsc_attr_builder_grow(builder);
|
wsc_attr_builder_grow(builder);
|
||||||
|
|
||||||
builder->buf[builder->offset + 4 + builder->curlen] = v;
|
builder->buf[builder->offset + builder->curlen] = v;
|
||||||
builder->curlen += 1;
|
builder->curlen += 1;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -1662,10 +1663,10 @@ static bool wsc_attr_builder_put_u8(struct wsc_attr_builder *builder, uint8_t v)
|
|||||||
static bool wsc_attr_builder_put_u16(struct wsc_attr_builder *builder,
|
static bool wsc_attr_builder_put_u16(struct wsc_attr_builder *builder,
|
||||||
uint16_t v)
|
uint16_t v)
|
||||||
{
|
{
|
||||||
if (builder->offset + 4 + builder->curlen + 2 >= builder->capacity)
|
if (builder->offset + builder->curlen + 2 >= builder->capacity)
|
||||||
wsc_attr_builder_grow(builder);
|
wsc_attr_builder_grow(builder);
|
||||||
|
|
||||||
l_put_be16(v, builder->buf + builder->offset + 4 + builder->curlen);
|
l_put_be16(v, builder->buf + builder->offset + builder->curlen);
|
||||||
builder->curlen += 2;
|
builder->curlen += 2;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -1674,10 +1675,10 @@ static bool wsc_attr_builder_put_u16(struct wsc_attr_builder *builder,
|
|||||||
static bool wsc_attr_builder_put_u32(struct wsc_attr_builder *builder,
|
static bool wsc_attr_builder_put_u32(struct wsc_attr_builder *builder,
|
||||||
uint32_t v)
|
uint32_t v)
|
||||||
{
|
{
|
||||||
if (builder->offset + 4 + builder->curlen + 4 >= builder->capacity)
|
if (builder->offset + builder->curlen + 4 >= builder->capacity)
|
||||||
wsc_attr_builder_grow(builder);
|
wsc_attr_builder_grow(builder);
|
||||||
|
|
||||||
l_put_be32(v, builder->buf + builder->offset + 4 + builder->curlen);
|
l_put_be32(v, builder->buf + builder->offset + builder->curlen);
|
||||||
builder->curlen += 4;
|
builder->curlen += 4;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -1686,12 +1687,10 @@ static bool wsc_attr_builder_put_u32(struct wsc_attr_builder *builder,
|
|||||||
static bool wsc_attr_builder_put_bytes(struct wsc_attr_builder *builder,
|
static bool wsc_attr_builder_put_bytes(struct wsc_attr_builder *builder,
|
||||||
const void *bytes, size_t size)
|
const void *bytes, size_t size)
|
||||||
{
|
{
|
||||||
while (builder->offset + 4 + builder->curlen + size >=
|
while (builder->offset + builder->curlen + size >= builder->capacity)
|
||||||
builder->capacity)
|
|
||||||
wsc_attr_builder_grow(builder);
|
wsc_attr_builder_grow(builder);
|
||||||
|
|
||||||
memcpy(builder->buf + builder->offset + 4 + builder->curlen,
|
memcpy(builder->buf + builder->offset + builder->curlen, bytes, size);
|
||||||
bytes, size);
|
|
||||||
builder->curlen += size;
|
builder->curlen += size;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -1700,10 +1699,10 @@ static bool wsc_attr_builder_put_bytes(struct wsc_attr_builder *builder,
|
|||||||
static bool wsc_attr_builder_put_oui(struct wsc_attr_builder *builder,
|
static bool wsc_attr_builder_put_oui(struct wsc_attr_builder *builder,
|
||||||
const uint8_t *oui)
|
const uint8_t *oui)
|
||||||
{
|
{
|
||||||
if (builder->offset + 4 + builder->curlen + 3 >= builder->capacity)
|
if (builder->offset + builder->curlen + 3 >= builder->capacity)
|
||||||
wsc_attr_builder_grow(builder);
|
wsc_attr_builder_grow(builder);
|
||||||
|
|
||||||
memcpy(builder->buf + builder->offset + 4 + builder->curlen, oui, 3);
|
memcpy(builder->buf + builder->offset + builder->curlen, oui, 3);
|
||||||
builder->curlen += 3;
|
builder->curlen += 3;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -1721,11 +1720,10 @@ static bool wsc_attr_builder_put_string(struct wsc_attr_builder *builder,
|
|||||||
len = 1;
|
len = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (builder->offset + 4 + builder->curlen + len >= builder->capacity)
|
if (builder->offset + builder->curlen + len >= builder->capacity)
|
||||||
wsc_attr_builder_grow(builder);
|
wsc_attr_builder_grow(builder);
|
||||||
|
|
||||||
memcpy(builder->buf + builder->offset + 4 + builder->curlen,
|
memcpy(builder->buf + builder->offset + builder->curlen, string, len);
|
||||||
string, len);
|
|
||||||
builder->curlen += len;
|
builder->curlen += len;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -1753,8 +1751,8 @@ static uint8_t *wsc_attr_builder_free(struct wsc_attr_builder *builder,
|
|||||||
|
|
||||||
if (builder->curlen > 0) {
|
if (builder->curlen > 0) {
|
||||||
uint8_t *bytes = builder->buf + builder->offset;
|
uint8_t *bytes = builder->buf + builder->offset;
|
||||||
l_put_be16(builder->curlen, bytes + 2);
|
l_put_be16(builder->curlen - 4, bytes + 2);
|
||||||
builder->offset += 4 + builder->curlen;
|
builder->offset += builder->curlen;
|
||||||
builder->curlen = 0;
|
builder->curlen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user