#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
/**
* \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, -ENOENT 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().
*/
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];
while (size > 0) {
unsigned int len;
err = snd_tlv_parse_dB_info(tlv, size, db_tlvp);
- if (err < 0)
+ if (err < 0 && err != -ENOENT)
return err; /* error */
if (err > 0)
return err; /* found */
default:
break;
}
- return -EINVAL; /* not found */
+ return -ENOENT;
}
/**