diff options
author | Paul McLean <pmclean@google.com> | 2015-04-04 13:28:27 -0700 |
---|---|---|
committer | Paul McLean <pmclean@google.com> | 2015-04-08 08:46:07 -0700 |
commit | 52dc113e5f9d9fa8dd18f4206c5e2927eecc7334 (patch) | |
tree | bdb4f8f2b65f58c0774086012a4f95e068adcdc4 /alsa_utils | |
parent | 5e460beac10672e6012d2ee834d573957b23db22 (diff) | |
download | android_system_media-52dc113e5f9d9fa8dd18f4206c5e2927eecc7334.tar.gz android_system_media-52dc113e5f9d9fa8dd18f4206c5e2927eecc7334.tar.bz2 android_system_media-52dc113e5f9d9fa8dd18f4206c5e2927eecc7334.zip |
fix sloppy strncat() building of sup_* strings.
Bug:
19933520
Change-Id: I7ba705d12b950df373054b52c93811094636fb18
Diffstat (limited to 'alsa_utils')
-rw-r--r-- | alsa_utils/alsa_device_profile.c | 106 |
1 files changed, 68 insertions, 38 deletions
diff --git a/alsa_utils/alsa_device_profile.c b/alsa_utils/alsa_device_profile.c index e6510b90..84886130 100644 --- a/alsa_utils/alsa_device_profile.c +++ b/alsa_utils/alsa_device_profile.c @@ -110,7 +110,7 @@ void profile_decache(alsa_device_profile* profile) { */ static unsigned int round_to_16_mult(unsigned int size) { - return (size + 15) & ~15; // 0xFFFFFFF0; + return (size + 15) & ~15; /* 0xFFFFFFF0; */ } /* @@ -132,7 +132,6 @@ unsigned profile_calc_min_period_size(alsa_device_profile* profile, unsigned sam unsigned int profile_get_period_size(alsa_device_profile* profile, unsigned sample_rate) { - // return profile->default_config.period_size; unsigned int period_size = profile_calc_min_period_size(profile, sample_rate); ALOGV("profile_get_period_size(rate:%d) = %d", sample_rate, period_size); return period_size; @@ -391,20 +390,32 @@ bool profile_read_device_info(alsa_device_profile* profile) char * profile_get_sample_rate_strs(alsa_device_profile* profile) { + /* if we assume that rate strings are about 5 characters (48000 is 5), plus ~1 for a + * delimiter "|" this buffer has room for about 22 rate strings which seems like + * way too much, but it's a stack variable so only temporary. + */ char buffer[128]; buffer[0] = '\0'; - int buffSize = ARRAY_SIZE(buffer); + size_t buffSize = ARRAY_SIZE(buffer); + size_t curStrLen = 0; char numBuffer[32]; - int numEntries = 0; - unsigned index; + size_t numEntries = 0; + size_t index; for (index = 0; profile->sample_rates[index] != 0; index++) { + snprintf(numBuffer, sizeof(numBuffer), "%u", profile->sample_rates[index]); + // account for both the null, and potentially the bar. + if (buffSize - curStrLen < strlen(numBuffer) + (numEntries != 0 ? 2 : 1)) { + /* we don't have room for another, so bail at this point rather than + * return a malformed rate string + */ + break; + } if (numEntries++ != 0) { - strncat(buffer, "|", buffSize); + strlcat(buffer, "|", buffSize); } - snprintf(numBuffer, sizeof(numBuffer), "%u", profile->sample_rates[index]); - strncat(buffer, numBuffer, buffSize); + curStrLen = strlcat(buffer, numBuffer, buffSize); } return strdup(buffer); @@ -417,17 +428,30 @@ char * profile_get_format_strs(alsa_device_profile* profile) return strdup("AUDIO_FORMAT_PCM_16_BIT"); } - char buffer[128]; + /* if we assume that format strings are about 24 characters (AUDIO_FORMAT_PCM_16_BIT is 23), + * plus ~1 for a delimiter "|" this buffer has room for about 10 format strings which seems + * like way too much, but it's a stack variable so only temporary. + */ + char buffer[256]; buffer[0] = '\0'; - int buffSize = ARRAY_SIZE(buffer); + size_t buffSize = ARRAY_SIZE(buffer); + size_t curStrLen = 0; - int numEntries = 0; - unsigned index = 0; + size_t numEntries = 0; + size_t index = 0; for (index = 0; profile->formats[index] != PCM_FORMAT_INVALID; index++) { + // account for both the null, and potentially the bar. + if (buffSize - curStrLen < strlen(format_string_map[profile->formats[index]]) + + (numEntries != 0 ? 2 : 1)) { + /* we don't have room for another, so bail at this point rather than + * return a malformed rate string + */ + break; + } if (numEntries++ != 0) { - strncat(buffer, "|", buffSize); + strlcat(buffer, "|", buffSize); } - strncat(buffer, format_string_map[profile->formats[index]], buffSize); + curStrLen = strlcat(buffer, format_string_map[profile->formats[index]], buffSize); } return strdup(buffer); @@ -444,7 +468,7 @@ char * profile_get_channel_count_strs(alsa_device_profile* profile) /* 5 */ /* "AUDIO_CHANNEL_OUT_QUAD|AUDIO_CHANNEL_OUT_FRONT_CENTER" */ NULL, /* 6 */"AUDIO_CHANNEL_OUT_5POINT1", /* 7 */ /* "AUDIO_CHANNEL_OUT_5POINT1|AUDIO_CHANNEL_OUT_BACK_CENTER" */ NULL, - /* 8 */"AUDIO_CHANNEL_OUT_7POINT1", + /* 8 */ "AUDIO_CHANNEL_OUT_7POINT1", /* channel counts greater than this not considered */ }; @@ -457,41 +481,47 @@ char * profile_get_channel_count_strs(alsa_device_profile* profile) const bool isOutProfile = profile->direction == PCM_OUT; - const char * const * const names_array = isOutProfile ? out_chans_strs : in_chans_strs; - const size_t names_size = isOutProfile ? ARRAY_SIZE(out_chans_strs) - : ARRAY_SIZE(in_chans_strs); + const char * const * const chans_strs = isOutProfile ? out_chans_strs : in_chans_strs; + const size_t chans_strs_size = + isOutProfile ? ARRAY_SIZE(out_chans_strs) : ARRAY_SIZE(in_chans_strs); + /* + * If we assume each channel string is 24 chars ("AUDIO_CHANNEL_OUT_7POINT1" is 25) + 1 for, + * the "|" delimiter, then we have room for about 10 strings (which is more than we + * currently support). + */ char buffer[256]; /* caution, may need to be expanded */ buffer[0] = '\0'; - const int buffer_size = ARRAY_SIZE(buffer); - int num_entries = 0; + size_t buffSize = ARRAY_SIZE(buffer); + size_t curStrLen = 0; + /* We currently support MONO and STEREO, and always report STEREO but some (many) * USB Audio Devices may only announce support for MONO (a headset mic for example), or * The total number of output channels. SO, if the device itself doesn't explicitly * support STEREO, append to the channel config strings we are generating. */ - bool stereo_present = false; - unsigned index; - unsigned channel_count; + // Always support stereo + curStrLen = strlcat(buffer, chans_strs[2], buffSize); - for (index = 0; (channel_count = profile->channel_counts[index]) != 0; index++) { - stereo_present = stereo_present || channel_count == 2; - if (channel_count < names_size && names_array[channel_count] != NULL) { - if (num_entries++ != 0) { - strncat(buffer, "|", buffer_size); + size_t index; + unsigned channel_count; + for (index = 0; + (channel_count = profile->channel_counts[index]) != 0 + && channel_count < chans_strs_size + && chans_strs[channel_count] != NULL; + index++) { + if (channel_count != 2) { + // account for the '|' and the '\0' + if (buffSize - curStrLen < strlen(chans_strs[channel_count]) + 2) { + /* we don't have room for another, so bail at this point rather than + * return a malformed rate string + */ + break; } - strncat(buffer, names_array[channel_count], buffer_size); - } - } - /* emulated modes: - * always expose stereo as we can emulate it for PCM_OUT - */ - if (!stereo_present) { - if (num_entries++ != 0) { - strncat(buffer, "|", buffer_size); + strlcat(buffer, "|", buffSize); + curStrLen = strlcat(buffer, chans_strs[channel_count], buffSize); } - strncat(buffer, names_array[2], buffer_size); /* stereo */ } return strdup(buffer); |