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/mvrp.c',
|
||||
'module-avb/srp.c',
|
||||
'module-avb/stream.c'
|
||||
'module-avb/stream.c',
|
||||
'module-avb/strings.c'
|
||||
],
|
||||
include_directories : [configinc],
|
||||
install : true,
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include "../aecp-aem.h"
|
||||
#include "../aecp-aem-state.h"
|
||||
#include "../aecp-aem-descriptors.h"
|
||||
#include "../strings.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
|
||||
* For now this is not handling UTF characters, only ASCII
|
||||
*/
|
||||
int handle_cmd_set_name_common(struct aecp *aecp, int64_t now,
|
||||
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;
|
||||
struct descriptor *desc;
|
||||
uint16_t desc_type, desc_id, name_index;
|
||||
char *name_ptr;
|
||||
unsigned char *name_ptr;
|
||||
int rc;
|
||||
|
||||
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,
|
||||
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)
|
||||
return reply_status(aecp,
|
||||
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
|
||||
* 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
|
||||
* terminated, the goal would be to check whether a string is UTF-8 and
|
||||
* that it is correctly zero terminitaed if less than 64 char, if not
|
||||
* then a simple memcpy is enough */
|
||||
if (validate_utf8(cmd->name, 64) == -1)
|
||||
return reply_status(aecp,
|
||||
AVB_AECP_AEM_STATUS_BAD_ARGUMENTS, m, len);
|
||||
|
||||
memcpy(name_ptr, cmd->name, 64);
|
||||
|
||||
rc = reply_success(aecp, m, len);
|
||||
if (rc < 0)
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ struct avb_packet_aecp_aem_setget_name {
|
|||
uint16_t descriptor_index;
|
||||
uint16_t name_index;
|
||||
uint16_t configuration_index;
|
||||
char name[64];
|
||||
unsigned char name[64];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
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