Skip to content

Commit

Permalink
libmyth: Prevent an access violation by the ALSA library
Browse files Browse the repository at this point in the history
In audiooutputalsa.cpp, AudioOutputALSA::GetALSADevices calls the
ALSA API snd_device_name_hint with a card index of -1 to obtain a list
of hints for all cards.  Unfortunately, with libasound.so.2.0 this API
can cause an access violation when the card index is -1.

Running with valgrind shows that snd_device_name_hint makes reference
to previously freed memory when the card index is -1.

This patch enumerates the cards using other ALSA APIs, thus avoiding
the SEGV.

Signed-off-by: Jean-Yves Avenard <jyavenard@mythtv.org>
  • Loading branch information
Lawrence Rust authored and jyavenard committed Jul 21, 2012
1 parent 0a5d426 commit c35c003
Showing 1 changed file with 35 additions and 17 deletions.
52 changes: 35 additions & 17 deletions mythtv/libs/libmyth/audio/audiooutputalsa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1011,26 +1011,44 @@ bool AudioOutputALSA::OpenMixer(void)
QMap<QString, QString> *AudioOutputALSA::GetDevices(const char *type)
{
QMap<QString, QString> *alsadevs = new QMap<QString, QString>();
void **hints, **n;
char *name, *desc;

if (snd_device_name_hint(-1, type, &hints) < 0)
return alsadevs;
n = hints;

while (*n != NULL)
// Loop through the sound cards to get Alsa device hints.
// NB Don't use snd_device_name_hint(-1,..) since there is a potential
// access violation using this ALSA API with libasound.so.2.0.0.
// See http://code.google.com/p/chromium/issues/detail?id=95797
int card = -1;
while (!snd_card_next(&card) && card >= 0)
{
name = snd_device_name_get_hint(*n, "NAME");
desc = snd_device_name_get_hint(*n, "DESC");
if (name && desc && strcmp(name, "null"))
alsadevs->insert(name, desc);
if (name)
free(name);
if (desc)
free(desc);
n++;
void** hints = NULL;
int error = snd_device_name_hint(card, type, &hints);
if (error == 0)
{
void *hint;
for (int i = 0; (hint = hints[i]) != NULL; ++i)
{
char *name = snd_device_name_get_hint(hint, "NAME");
if (name)
{
char *desc = snd_device_name_get_hint(hint, "DESC");
if (desc)
{
if (strcmp(name, "null"))
alsadevs->insert(name, desc);
free(desc);
}
free(name);
}
}

snd_device_name_free_hint(hints);
}
else
{
VBERROR(QString("Failed to get device hints for card %1, error %2")
.arg(card).arg(error));
}
}
snd_device_name_free_hint(hints);

// Work around ALSA bug < 1.0.22 ; where snd_device_name_hint can corrupt
// global ALSA memory context
#if SND_LIB_MAJOR == 1
Expand Down

0 comments on commit c35c003

Please sign in to comment.