mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-05-29 21:37:54 -04:00
Merge branch 'get-set-name-string-validity' into 'master'
module-avb: SET_NAME string validity checks Closes #5286 See merge request pipewire/pipewire!2838
This commit is contained in:
commit
6a4403abce
5 changed files with 191 additions and 11 deletions
|
|
@ -828,7 +828,8 @@ if build_module_avb
|
||||||
'module-avb/msrp.c',
|
'module-avb/msrp.c',
|
||||||
'module-avb/mvrp.c',
|
'module-avb/mvrp.c',
|
||||||
'module-avb/srp.c',
|
'module-avb/srp.c',
|
||||||
'module-avb/stream.c'
|
'module-avb/stream.c',
|
||||||
|
'module-avb/strings.c'
|
||||||
],
|
],
|
||||||
include_directories : [configinc],
|
include_directories : [configinc],
|
||||||
install : true,
|
install : true,
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
#include "../aecp-aem.h"
|
#include "../aecp-aem.h"
|
||||||
#include "../aecp-aem-state.h"
|
#include "../aecp-aem-state.h"
|
||||||
#include "../aecp-aem-descriptors.h"
|
#include "../aecp-aem-descriptors.h"
|
||||||
|
#include "../strings.h"
|
||||||
|
|
||||||
|
|
||||||
#include "cmd-get-set-name.h"
|
#include "cmd-get-set-name.h"
|
||||||
|
|
@ -145,7 +146,6 @@ int handle_cmd_get_name_common(struct aecp *aecp, int64_t now,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IEEE 1722.1-2021 7.4.17 SET_NAME
|
* IEEE 1722.1-2021 7.4.17 SET_NAME
|
||||||
* For now this is not handling UTF characters, only ASCII
|
|
||||||
*/
|
*/
|
||||||
int handle_cmd_set_name_common(struct aecp *aecp, int64_t now,
|
int handle_cmd_set_name_common(struct aecp *aecp, int64_t now,
|
||||||
const void *m, int len)
|
const void *m, int len)
|
||||||
|
|
@ -156,7 +156,7 @@ int handle_cmd_set_name_common(struct aecp *aecp, int64_t now,
|
||||||
const struct avb_packet_aecp_aem_setget_name *cmd;
|
const struct avb_packet_aecp_aem_setget_name *cmd;
|
||||||
struct descriptor *desc;
|
struct descriptor *desc;
|
||||||
uint16_t desc_type, desc_id, name_index;
|
uint16_t desc_type, desc_id, name_index;
|
||||||
char *name_ptr;
|
unsigned char *name_ptr;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
cmd = (const struct avb_packet_aecp_aem_setget_name *)p->payload;
|
cmd = (const struct avb_packet_aecp_aem_setget_name *)p->payload;
|
||||||
|
|
@ -169,7 +169,7 @@ int handle_cmd_set_name_common(struct aecp *aecp, int64_t now,
|
||||||
return reply_status(aecp,
|
return reply_status(aecp,
|
||||||
AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, m, len);
|
AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, m, len);
|
||||||
|
|
||||||
name_ptr = get_name_ptr(desc_type, descriptor_body(desc), name_index);
|
name_ptr = (unsigned char *)get_name_ptr(desc_type, descriptor_body(desc), name_index);
|
||||||
if (name_ptr == NULL)
|
if (name_ptr == NULL)
|
||||||
return reply_status(aecp,
|
return reply_status(aecp,
|
||||||
AVB_AECP_AEM_STATUS_BAD_ARGUMENTS, m, len);
|
AVB_AECP_AEM_STATUS_BAD_ARGUMENTS, m, len);
|
||||||
|
|
@ -181,14 +181,17 @@ int handle_cmd_set_name_common(struct aecp *aecp, int64_t now,
|
||||||
/**
|
/**
|
||||||
* IEEE 1722.1-2021: 7.4.17.1: The name does not contain a trailing NULL
|
* IEEE 1722.1-2021: 7.4.17.1: The name does not contain a trailing NULL
|
||||||
* but if the name is less than 64 bytes in length then it is zero
|
* but if the name is less than 64 bytes in length then it is zero
|
||||||
* padded
|
* padded.
|
||||||
*/
|
*/
|
||||||
memcpy(name_ptr, cmd->name, 64);
|
if (check_zero_padding(cmd->name, 64) == -1)
|
||||||
|
return reply_status(aecp,
|
||||||
|
AVB_AECP_AEM_STATUS_BAD_ARGUMENTS, m, len);
|
||||||
|
|
||||||
/** TODO: According to the specification, the string should alwasy be 0
|
if (validate_utf8(cmd->name, 64) == -1)
|
||||||
* terminated, the goal would be to check whether a string is UTF-8 and
|
return reply_status(aecp,
|
||||||
* that it is correctly zero terminitaed if less than 64 char, if not
|
AVB_AECP_AEM_STATUS_BAD_ARGUMENTS, m, len);
|
||||||
* then a simple memcpy is enough */
|
|
||||||
|
memcpy(name_ptr, cmd->name, 64);
|
||||||
|
|
||||||
rc = reply_success(aecp, m, len);
|
rc = reply_success(aecp, m, len);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
|
|
|
||||||
|
|
@ -250,7 +250,7 @@ struct avb_packet_aecp_aem_setget_name {
|
||||||
uint16_t descriptor_index;
|
uint16_t descriptor_index;
|
||||||
uint16_t name_index;
|
uint16_t name_index;
|
||||||
uint16_t configuration_index;
|
uint16_t configuration_index;
|
||||||
char name[64];
|
unsigned char name[64];
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
struct avb_packet_aecp_aem_setget_association_id {
|
struct avb_packet_aecp_aem_setget_association_id {
|
||||||
|
|
|
||||||
162
src/modules/module-avb/strings.c
Normal file
162
src/modules/module-avb/strings.c
Normal file
|
|
@ -0,0 +1,162 @@
|
||||||
|
/* SPDX-FileCopyrightText: Copyright © 2026 Nils Tonnaett
|
||||||
|
* Nils Tonnaett <ntonnatt@ccrma.stanford.edu> */
|
||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
|
||||||
|
#include "strings.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ST_START,
|
||||||
|
ST_A,
|
||||||
|
ST_B,
|
||||||
|
ST_C,
|
||||||
|
ST_D,
|
||||||
|
ST_E,
|
||||||
|
ST_F,
|
||||||
|
ST_G,
|
||||||
|
} UTF8_STATE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IEEE 1722.1 Section 7.4.17.1
|
||||||
|
*
|
||||||
|
* We need to check if the buffer str of length len is valid UTF-8.
|
||||||
|
* The algorithm implemented here is based on the state machine by Frank Yung-Fong Tang
|
||||||
|
* described here at
|
||||||
|
* https://unicode.org/mail-arch/unicode-ml/y2003-m02/att-0467/01-The_Algorithm_to_Valide_an_UTF-8_String
|
||||||
|
*/
|
||||||
|
int validate_utf8 (const unsigned char *str, size_t len)
|
||||||
|
{
|
||||||
|
UTF8_STATE state = ST_START;
|
||||||
|
bool err = false;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < len; ++i)
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case ST_START:
|
||||||
|
if (str[i] <= 0x7F)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (str[i] >= 0xC2 && str[i] <= 0xDF)
|
||||||
|
{
|
||||||
|
state = ST_A;
|
||||||
|
}
|
||||||
|
else if (str[i] >= 0xE1 && str[i] <= 0xEC)
|
||||||
|
{
|
||||||
|
state = ST_B;
|
||||||
|
}
|
||||||
|
else if (str[i] >= 0xEE && str[i] <= 0xEF)
|
||||||
|
{
|
||||||
|
state = ST_B;
|
||||||
|
}
|
||||||
|
else if (str[i] == 0xE0)
|
||||||
|
{
|
||||||
|
state = ST_C;
|
||||||
|
}
|
||||||
|
else if (str[i] == 0xED)
|
||||||
|
{
|
||||||
|
state = ST_D;
|
||||||
|
}
|
||||||
|
else if (str[i] >= 0xF1 && str[i] <= 0xF3)
|
||||||
|
{
|
||||||
|
state = ST_E;
|
||||||
|
}
|
||||||
|
else if (str[i] == 0xF0)
|
||||||
|
{
|
||||||
|
state = ST_F;
|
||||||
|
}
|
||||||
|
else if (str[i] >= 0xF4)
|
||||||
|
{
|
||||||
|
state = ST_G;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
err = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ST_A:
|
||||||
|
if (str[i] >= 0x80 && str[i] <= 0xBF)
|
||||||
|
state = ST_START;
|
||||||
|
else
|
||||||
|
err = true;
|
||||||
|
break;
|
||||||
|
case ST_B:
|
||||||
|
if (str[i] >= 0x80 && str[i] <= 0xBF)
|
||||||
|
state = ST_A;
|
||||||
|
else
|
||||||
|
err = true;
|
||||||
|
break;
|
||||||
|
case ST_C:
|
||||||
|
if (str[i] >= 0xA0 && str[i] <= 0xBF)
|
||||||
|
state = ST_A;
|
||||||
|
else
|
||||||
|
err = true;
|
||||||
|
break;
|
||||||
|
case ST_D:
|
||||||
|
if (str[i] >= 0x80 && str[i] <= 0x9F)
|
||||||
|
state = ST_A;
|
||||||
|
else
|
||||||
|
err = true;
|
||||||
|
break;
|
||||||
|
case ST_E:
|
||||||
|
if (str[i] >= 0x80 && str[i] <= 0xBF)
|
||||||
|
state = ST_B;
|
||||||
|
else
|
||||||
|
err = true;
|
||||||
|
break;
|
||||||
|
case ST_F:
|
||||||
|
if (str[i] >= 0x90 && str[i] <= 0xBF)
|
||||||
|
state = ST_B;
|
||||||
|
else
|
||||||
|
err = true;
|
||||||
|
break;
|
||||||
|
case ST_G:
|
||||||
|
if (str[i] >= 0x80 && str[i] <= 0x8F)
|
||||||
|
state = ST_B;
|
||||||
|
else
|
||||||
|
err = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (err == true)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (state != ST_START)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For SET_NAME, strings need to be zero-padded if shorter than 64 bytes. A
|
||||||
|
* string of 64 bytes would NOT be nul-terminated.
|
||||||
|
*
|
||||||
|
* IEEE 1722.1 Section 7.4.17.1
|
||||||
|
*/
|
||||||
|
int check_zero_padding (const unsigned char *str, size_t len)
|
||||||
|
{
|
||||||
|
size_t str_len = strnlen ((char *)str, len);
|
||||||
|
/* String doesn't need to be null-terminated. Return success if there is no
|
||||||
|
* null in str */
|
||||||
|
if (str_len == len)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i = str_len; i < len; ++i)
|
||||||
|
{
|
||||||
|
if (str[i] != 0x00)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
14
src/modules/module-avb/strings.h
Normal file
14
src/modules/module-avb/strings.h
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
/* SPDX-FileCopyrightText: Copyright © 2026 Nils Tonnaett*/
|
||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
|
||||||
|
#ifndef AVB_STRINGS_H
|
||||||
|
#define AVB_STRINGS_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int check_zero_padding(const unsigned char *str, size_t len);
|
||||||
|
int validate_utf8(const unsigned char *str, size_t len);
|
||||||
|
|
||||||
|
#endif /* AVB_STRINGS_H */
|
||||||
Loading…
Add table
Add a link
Reference in a new issue