Re: [BlueZ 9/9] avdtp: Fix manipulating struct as an array

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

to, 2024-05-30 kello 16:58 +0200, Bastien Nocera kirjoitti:
> Don't manipulate the "req" structs as if they were flat arrays, static
> analysis and humans are both equally confused by this kind of usage.

struct start_req {
	union {
		struct seid required[1];
		struct seid seids[0];
	};
} __attribute__ ((packed));

and access only via req->seids?

> 
> Error: ARRAY_VS_SINGLETON (CWE-119): [#def26] [important]
> bluez-5.76/profiles/audio/avdtp.c:1675:2: address_of: Taking address with "&start->first_seid" yields a singleton pointer.
> bluez-5.76/profiles/audio/avdtp.c:1675:2: assign: Assigning: "seid" = "&start->first_seid".
> bluez-5.76/profiles/audio/avdtp.c:1679:25: ptr_arith: Using "seid" as an array.  This might corrupt or misinterpret adjacent memory locations.
> 1677|           int i;
> 1678|
> 1679|->         for (i = 0; i < count; i++, seid++) {
> 1680|                   if (seid->seid == id) {
> 1681|                           req->collided = TRUE;
> 
> Error: ARRAY_VS_SINGLETON (CWE-119): [#def27] [important]
> bluez-5.76/profiles/audio/avdtp.c:1690:2: address_of: Taking address with "&suspend->first_seid" yields a singleton pointer.
> bluez-5.76/profiles/audio/avdtp.c:1690:2: assign: Assigning: "seid" = "&suspend->first_seid".
> bluez-5.76/profiles/audio/avdtp.c:1694:25: ptr_arith: Using "seid" as an array.  This might corrupt or misinterpret adjacent memory locations.
> 1692|		int i;
> 1693|
> 1694|->		for (i = 0; i < count; i++, seid++) {
> 1695|			if (seid->seid == id) {
> 1696|				req->collided = TRUE;
> 
> Error: ARRAY_VS_SINGLETON (CWE-119): [#def28] [important]
> bluez-5.76/profiles/audio/avdtp.c:1799:2: address_of: Taking address with "&req->first_seid" yields a singleton pointer.
> bluez-5.76/profiles/audio/avdtp.c:1799:2: assign: Assigning: "seid" = "&req->first_seid".
> bluez-5.76/profiles/audio/avdtp.c:1801:30: ptr_arith: Using "seid" as an array.  This might corrupt or misinterpret adjacent memory locations.
> 1799|		seid = &req->first_seid;
> 1800|
> 1801|->		for (i = 0; i < seid_count; i++, seid++) {
> 1802|			failed_seid = seid->seid;
> 1803|
> 
> Error: ARRAY_VS_SINGLETON (CWE-119): [#def29] [important]
> bluez-5.76/profiles/audio/avdtp.c:1912:2: address_of: Taking address with "&req->first_seid" yields a singleton pointer.
> bluez-5.76/profiles/audio/avdtp.c:1912:2: assign: Assigning: "seid" = "&req->first_seid".
> bluez-5.76/profiles/audio/avdtp.c:1914:30: ptr_arith: Using "seid" as an array.  This might corrupt or misinterpret adjacent memory locations.
> 1912|		seid = &req->first_seid;
> 1913|
> 1914|->	for (i = 0; i < seid_count; i++, seid++) {
> 1915|			failed_seid = seid->seid;
> 1916|
> ---
>  profiles/audio/avdtp.c | 33 ++++++++++++++++++++++-----------
>  1 file changed, 22 insertions(+), 11 deletions(-)
> 
> diff --git a/profiles/audio/avdtp.c b/profiles/audio/avdtp.c
> index 3667e08400dd..38c1870e619d 100644
> --- a/profiles/audio/avdtp.c
> +++ b/profiles/audio/avdtp.c
> @@ -429,6 +429,20 @@ static void avdtp_sep_set_state(struct avdtp *session,
>  				struct avdtp_local_sep *sep,
>  				avdtp_state_t state);
>  
> +#define REQ_GET_NTH_SEID(x)						\
> +	static struct seid *						\
> +	x##_req_get_nth_seid(struct x##_req *req, int count, int i)	\
> +	{								\
> +		if (count == 0 || i >= count)				\
> +			return NULL;					\
> +		if (i == 1)						\
> +			return &req->first_seid;			\
> +		return &req->other_seids[i];				\

(i == 0) and [i - 1]?

> +	}
> +
> +REQ_GET_NTH_SEID(start)
> +REQ_GET_NTH_SEID(suspend)
> +
>  static const char *avdtp_statestr(avdtp_state_t state)
>  {
>  	switch (state) {
> @@ -1672,11 +1686,11 @@ static void check_seid_collision(struct pending_req *req, uint8_t id)
>  static void check_start_collision(struct pending_req *req, uint8_t id)
>  {
>  	struct start_req *start = req->data;
> -	struct seid *seid = &start->first_seid;
>  	int count = 1 + req->data_size - sizeof(struct start_req);
>  	int i;
>  
> -	for (i = 0; i < count; i++, seid++) {
> +	for (i = 0; i < count; i++) {
> +		struct seid *seid = start_req_get_nth_seid(start, count, i);
>  		if (seid->seid == id) {
>  			req->collided = TRUE;
>  			return;
> @@ -1687,11 +1701,11 @@ static void check_start_collision(struct pending_req *req, uint8_t id)
>  static void check_suspend_collision(struct pending_req *req, uint8_t id)
>  {
>  	struct suspend_req *suspend = req->data;
> -	struct seid *seid = &suspend->first_seid;
>  	int count = 1 + req->data_size - sizeof(struct suspend_req);
>  	int i;
>  
> -	for (i = 0; i < count; i++, seid++) {
> +	for (i = 0; i < count; i++) {
> +		struct seid *seid = suspend_req_get_nth_seid(suspend, count, i);
>  		if (seid->seid == id) {
>  			req->collided = TRUE;
>  			return;
> @@ -1785,7 +1799,6 @@ static gboolean avdtp_start_cmd(struct avdtp *session, uint8_t transaction,
>  	struct avdtp_local_sep *sep;
>  	struct avdtp_stream *stream;
>  	struct stream_rej rej;
> -	struct seid *seid;
>  	uint8_t err, failed_seid;
>  	int seid_count, i;
>  
> @@ -1796,9 +1809,9 @@ static gboolean avdtp_start_cmd(struct avdtp *session, uint8_t transaction,
>  
>  	seid_count = 1 + size - sizeof(struct start_req);
>  
> -	seid = &req->first_seid;
> +	for (i = 0; i < seid_count; i++) {
> +		struct seid *seid = start_req_get_nth_seid(req, seid_count, i);
>  
> -	for (i = 0; i < seid_count; i++, seid++) {
>  		failed_seid = seid->seid;
>  
>  		sep = find_local_sep_by_seid(session, seid->seid);
> @@ -1898,7 +1911,6 @@ static gboolean avdtp_suspend_cmd(struct avdtp *session, uint8_t transaction,
>  	struct avdtp_local_sep *sep;
>  	struct avdtp_stream *stream;
>  	struct stream_rej rej;
> -	struct seid *seid;
>  	uint8_t err, failed_seid;
>  	int seid_count, i;
>  
> @@ -1909,9 +1921,8 @@ static gboolean avdtp_suspend_cmd(struct avdtp *session, uint8_t transaction,
>  
>  	seid_count = 1 + size - sizeof(struct suspend_req);
>  
> -	seid = &req->first_seid;
> -
> -	for (i = 0; i < seid_count; i++, seid++) {
> +	for (i = 0; i < seid_count; i++) {
> +		struct seid *seid = suspend_req_get_nth_seid(req, seid_count, i);
>  		failed_seid = seid->seid;
>  
>  		sep = find_local_sep_by_seid(session, seid->seid);






[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux