mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-29 05:40:25 -04:00
Fix TLV dB parser in case of used container
In case when dB information does not appear as the only TLV type in the stream (it might be wrapped in a container, but the container can not have any other type), the TLV parser fails to get the dB TLV pointer. This commit fixes it by distinguishing between TLV parse error and dB information not being found in a container, so the parser can iterate over all elements in the container. Also, it fixes out-of-bounds read in case of malicious TLV record. Signed-off-by: Arkadiusz Bokowy <arkadiusz.bokowy@gmail.com>
This commit is contained in:
parent
645668dca2
commit
6d4159d00d
1 changed files with 14 additions and 5 deletions
|
|
@ -40,6 +40,8 @@
|
|||
#define int_index(size) (((size) + sizeof(int) - 1) / sizeof(int))
|
||||
/* max size of a TLV entry for dB information (including compound one) */
|
||||
#define MAX_TLV_RANGE_SIZE 256
|
||||
/* min length of a TLV stream to contain type and size */
|
||||
#define MIN_TLV_STREAM_LEN ((SNDRV_CTL_TLVO_LEN + 1) * sizeof(int))
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
@ -47,12 +49,12 @@
|
|||
* \param tlv the TLV source
|
||||
* \param tlv_size the byte size of TLV source
|
||||
* \param db_tlvp the pointer stored the dB TLV information
|
||||
* \return the byte size of dB TLV information if found in the given
|
||||
* TLV source, or a negative error code.
|
||||
* \return The byte size of dB TLV information if found in the given TLV
|
||||
* source, zero if not found, or a negative error code in case of an error.
|
||||
*
|
||||
* This function parses the given TLV source and stores the TLV start
|
||||
* point if the TLV information regarding dB conversion is found.
|
||||
* The stored TLV pointer can be passed to the convesion functions
|
||||
* The stored TLV pointer can be passed to the conversion functions
|
||||
* #snd_tlv_convert_to_dB(), #snd_tlv_convert_from_dB() and
|
||||
* #snd_tlv_get_dB_range().
|
||||
*/
|
||||
|
|
@ -64,6 +66,13 @@ int snd_tlv_parse_dB_info(unsigned int *tlv,
|
|||
unsigned int size;
|
||||
int err;
|
||||
|
||||
/* Validate that it is possible to read the type and size
|
||||
* without reading past the end of the buffer. */
|
||||
if (tlv_size < MIN_TLV_STREAM_LEN) {
|
||||
SNDERR("TLV stream too short");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*db_tlvp = NULL;
|
||||
type = tlv[SNDRV_CTL_TLVO_TYPE];
|
||||
size = tlv[SNDRV_CTL_TLVO_LEN];
|
||||
|
|
@ -76,7 +85,7 @@ int snd_tlv_parse_dB_info(unsigned int *tlv,
|
|||
case SND_CTL_TLVT_CONTAINER:
|
||||
size = int_index(size) * sizeof(int);
|
||||
tlv += 2;
|
||||
while (size > 0) {
|
||||
while (size >= MIN_TLV_STREAM_LEN) {
|
||||
unsigned int len;
|
||||
err = snd_tlv_parse_dB_info(tlv, size, db_tlvp);
|
||||
if (err < 0)
|
||||
|
|
@ -114,7 +123,7 @@ int snd_tlv_parse_dB_info(unsigned int *tlv,
|
|||
default:
|
||||
break;
|
||||
}
|
||||
return -EINVAL; /* not found */
|
||||
return 0; /* not found */
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue