Re: sio_initpar() generates invalid parameters

From: Alexandre Ratchov <alex_at_caoua.org>
Date: Tue, 15 Jun 2021 16:58:12 +0200
On Fri, Jun 11, 2021 at 08:01:35PM +0400, Roman Bogorodskiy wrote:
> Hi,
> 
> I have sndio-1.7.0 on FreeBSD. My initial problem that mpg123 wasn't
> working with sndio backend (and oss backend worked fine). I've reported
> the problem here: https://sourceforge.net/p/mpg123/bugs/314/
> 
> It turns out that the problem might be actually on sndio side.
> 
> Specifically, it looks like sio_oss_setpar() fails on setting CHANNELS
> which are coming unchanged from a structure initialized by
> sio_initpar().
> 
> Thomas Orgis has shared the following test code:
> 
> 
> #include <sndio.h>
> #include <stdio.h>
> 
> int main()
> {
> 	int ret=1;
> 	struct sio_hdl *hdl;
> 	struct sio_par par;
> 	sio_initpar(&par);
> //	par.pchan = 0;
> 	printf("initpar channels: %u\n", par.pchan);
> 	hdl = sio_open(NULL, SIO_PLAY, 0);
> 	if(!hdl)
> 		return ret;
> 	printf("opened\n");
> 	if(sio_setpar(hdl, &par))
> 	{
> 		printf("setpar successful\n");
> 		struct sio_par par2;
> 		sio_initpar(&par2);
> 		if(sio_getpar(hdl, &par2))
> 		{
> 			printf("default format: %u ch, %u Hz\n", par2.pchan, par2.rate);
> 			ret = 0;
> 		} else
> 			printf("failure in getpar\n");
> 	} else
> 		printf("failure in setpar\n");
> 	sio_close(hdl);
> 	return ret;
> }
> 
> With "par.pchan = 0" line commented out it fails:
> 
> $ SNDIO_DEBUG=2 ./sndiotest
> initpar channels: 4294967295
> _aucat_open: host= unit=0 devnum=0 opt=default
> /tmp/sndio-1001/sock0: No such file or directory
> /tmp/sndio/sock0: No such file or directory
> opened
> sio_oss_setpar: CHANNELS: Invalid argument
> failure in setpar
> 
> With that line uncommented it works:
> 
> SNDIO_DEBUG=2 ./sndiotest                                                 
> initpar channels: 0
> _aucat_open: host= unit=0 devnum=0 opt=default
> /tmp/sndio-1001/sock0: No such file or directory
> /tmp/sndio/sock0: No such file or directory
> opened
> setpar successful
> default format: 1 ch, 48000 Hz
> 
> Quoting the manpage:
> 
>      •   Initialize a sio_par structure using sio_initpar() and fill it with
>          the desired parameters.  Then call sio_setpar() to request the device
>          to use them.  Parameters left unset in the sio_par structure will be
>          set to device-specific defaults.
> 
> As in the failing case we don't override 'par.pchat', should not it use
> some reasonable device-specific default which allows sio_initpar() to
> complete successfully?
> 

sio_initpar() fills all parameters with -1, which is a trap value
meaning "don't change this parameter" (parameter is unset). In turn,
the default should be used as you said.

The problem is that sio_oss_setpar() doesn't check if the channel
number is unset (equals to the trap value) and tries to set it to ~0U.

I have no FreeBSD system right now, does this diff fix the problem?

diff --git a/libsndio/sio_oss.c b/libsndio/sio_oss.c
index 6a171c1..22c37fc 100644
--- a/libsndio/sio_oss.c
+++ b/libsndio/sio_oss.c
_at_@ -436,9 +436,9 @@ sio_oss_setpar(struct sio_hdl *sh, struct sio_par *par)
 	if (hdl->rate > 192000)
 		hdl->rate = 192000;
 
-	if (hdl->sio.mode & SIO_PLAY)
+	if ((hdl->sio.mode & SIO_PLAY) && par->pchan != ~0U)
 		hdl->chan = par->pchan;
-	else if (hdl->sio.mode & SIO_REC)
+	else if ((hdl->sio.mode & SIO_REC) && par->rchan != ~0U)
 		hdl->chan = par->rchan;
 
 	if (ioctl(hdl->fd, SNDCTL_DSP_SETFMT, &hdl->fmt) == -1) {
Received on Tue Jun 15 2021 - 16:58:12 CEST

This archive was generated by hypermail 2.3.0 : Wed Jun 16 2021 - 01:34:03 CEST