Issue #12287: In ossaudiodev, check that the device isn't closed in several

methods.
This commit is contained in:
Charles-François Natali 2011-06-11 18:58:24 +02:00
parent d8649b1a1a
commit a529308348
3 changed files with 110 additions and 0 deletions

View File

@ -170,6 +170,22 @@ class OSSAudioDevTests(unittest.TestCase):
pass pass
self.assertTrue(dsp.closed) self.assertTrue(dsp.closed)
def test_on_closed(self):
dsp = ossaudiodev.open('w')
dsp.close()
self.assertRaises(ValueError, dsp.fileno)
self.assertRaises(ValueError, dsp.read, 1)
self.assertRaises(ValueError, dsp.write, b'x')
self.assertRaises(ValueError, dsp.writeall, b'x')
self.assertRaises(ValueError, dsp.bufsize)
self.assertRaises(ValueError, dsp.obufcount)
self.assertRaises(ValueError, dsp.obufcount)
self.assertRaises(ValueError, dsp.obuffree)
self.assertRaises(ValueError, dsp.getptr)
mixer = ossaudiodev.openmixer()
mixer.close()
self.assertRaises(ValueError, mixer.fileno)
def test_main(): def test_main():
try: try:

View File

@ -187,6 +187,9 @@ Core and Builtins
Library Library
------- -------
- Issue #12287: In ossaudiodev, check that the device isn't closed in several
methods.
- Issue #12009: Fixed regression in netrc file comment handling. - Issue #12009: Fixed regression in netrc file comment handling.
- Issue #12246: Warn and fail when trying to install a third-party project from - Issue #12246: Warn and fail when trying to install a third-party project from

View File

@ -213,6 +213,21 @@ oss_mixer_dealloc(oss_mixer_t *self)
* Helper functions * Helper functions
*/ */
/* Check if a given file descriptor is valid (i.e. hasn't been closed).
* If true, return 1. Otherwise, raise ValueError and return 0.
*/
static int _is_fd_valid(int fd)
{
/* the FD is set to -1 in oss_close()/oss_mixer_close() */
if (fd >= 0) {
return 1;
} else {
PyErr_SetString(PyExc_ValueError,
"Operation on closed OSS device.");
return 0;
}
}
/* _do_ioctl_1() is a private helper function used for the OSS ioctls -- /* _do_ioctl_1() is a private helper function used for the OSS ioctls --
SNDCTL_DSP_{SETFMT,CHANNELS,SPEED} -- that that are called from C SNDCTL_DSP_{SETFMT,CHANNELS,SPEED} -- that that are called from C
like this: like this:
@ -300,6 +315,9 @@ _do_ioctl_0(int fd, PyObject *args, char *fname, int cmd)
static PyObject * static PyObject *
oss_nonblock(oss_audio_t *self, PyObject *unused) oss_nonblock(oss_audio_t *self, PyObject *unused)
{ {
if (!_is_fd_valid(self->fd))
return NULL;
/* Hmmm: it doesn't appear to be possible to return to blocking /* Hmmm: it doesn't appear to be possible to return to blocking
mode once we're in non-blocking mode! */ mode once we're in non-blocking mode! */
if (ioctl(self->fd, SNDCTL_DSP_NONBLOCK, NULL) == -1) if (ioctl(self->fd, SNDCTL_DSP_NONBLOCK, NULL) == -1)
@ -311,6 +329,9 @@ oss_nonblock(oss_audio_t *self, PyObject *unused)
static PyObject * static PyObject *
oss_setfmt(oss_audio_t *self, PyObject *args) oss_setfmt(oss_audio_t *self, PyObject *args)
{ {
if (!_is_fd_valid(self->fd))
return NULL;
return _do_ioctl_1(self->fd, args, "setfmt", SNDCTL_DSP_SETFMT); return _do_ioctl_1(self->fd, args, "setfmt", SNDCTL_DSP_SETFMT);
} }
@ -318,6 +339,10 @@ static PyObject *
oss_getfmts(oss_audio_t *self, PyObject *unused) oss_getfmts(oss_audio_t *self, PyObject *unused)
{ {
int mask; int mask;
if (!_is_fd_valid(self->fd))
return NULL;
if (ioctl(self->fd, SNDCTL_DSP_GETFMTS, &mask) == -1) if (ioctl(self->fd, SNDCTL_DSP_GETFMTS, &mask) == -1)
return PyErr_SetFromErrno(PyExc_IOError); return PyErr_SetFromErrno(PyExc_IOError);
return PyLong_FromLong(mask); return PyLong_FromLong(mask);
@ -326,30 +351,45 @@ oss_getfmts(oss_audio_t *self, PyObject *unused)
static PyObject * static PyObject *
oss_channels(oss_audio_t *self, PyObject *args) oss_channels(oss_audio_t *self, PyObject *args)
{ {
if (!_is_fd_valid(self->fd))
return NULL;
return _do_ioctl_1(self->fd, args, "channels", SNDCTL_DSP_CHANNELS); return _do_ioctl_1(self->fd, args, "channels", SNDCTL_DSP_CHANNELS);
} }
static PyObject * static PyObject *
oss_speed(oss_audio_t *self, PyObject *args) oss_speed(oss_audio_t *self, PyObject *args)
{ {
if (!_is_fd_valid(self->fd))
return NULL;
return _do_ioctl_1(self->fd, args, "speed", SNDCTL_DSP_SPEED); return _do_ioctl_1(self->fd, args, "speed", SNDCTL_DSP_SPEED);
} }
static PyObject * static PyObject *
oss_sync(oss_audio_t *self, PyObject *args) oss_sync(oss_audio_t *self, PyObject *args)
{ {
if (!_is_fd_valid(self->fd))
return NULL;
return _do_ioctl_0(self->fd, args, "sync", SNDCTL_DSP_SYNC); return _do_ioctl_0(self->fd, args, "sync", SNDCTL_DSP_SYNC);
} }
static PyObject * static PyObject *
oss_reset(oss_audio_t *self, PyObject *args) oss_reset(oss_audio_t *self, PyObject *args)
{ {
if (!_is_fd_valid(self->fd))
return NULL;
return _do_ioctl_0(self->fd, args, "reset", SNDCTL_DSP_RESET); return _do_ioctl_0(self->fd, args, "reset", SNDCTL_DSP_RESET);
} }
static PyObject * static PyObject *
oss_post(oss_audio_t *self, PyObject *args) oss_post(oss_audio_t *self, PyObject *args)
{ {
if (!_is_fd_valid(self->fd))
return NULL;
return _do_ioctl_0(self->fd, args, "post", SNDCTL_DSP_POST); return _do_ioctl_0(self->fd, args, "post", SNDCTL_DSP_POST);
} }
@ -364,6 +404,9 @@ oss_read(oss_audio_t *self, PyObject *args)
char *cp; char *cp;
PyObject *rv; PyObject *rv;
if (!_is_fd_valid(self->fd))
return NULL;
if (!PyArg_ParseTuple(args, "i:read", &size)) if (!PyArg_ParseTuple(args, "i:read", &size))
return NULL; return NULL;
rv = PyBytes_FromStringAndSize(NULL, size); rv = PyBytes_FromStringAndSize(NULL, size);
@ -391,6 +434,9 @@ oss_write(oss_audio_t *self, PyObject *args)
char *cp; char *cp;
int rv, size; int rv, size;
if (!_is_fd_valid(self->fd))
return NULL;
if (!PyArg_ParseTuple(args, "y#:write", &cp, &size)) { if (!PyArg_ParseTuple(args, "y#:write", &cp, &size)) {
return NULL; return NULL;
} }
@ -422,6 +468,9 @@ oss_writeall(oss_audio_t *self, PyObject *args)
mode, the behaviour of write() and writeall() from Python is mode, the behaviour of write() and writeall() from Python is
indistinguishable. */ indistinguishable. */
if (!_is_fd_valid(self->fd))
return NULL;
if (!PyArg_ParseTuple(args, "y#:write", &cp, &size)) if (!PyArg_ParseTuple(args, "y#:write", &cp, &size))
return NULL; return NULL;
@ -489,6 +538,9 @@ oss_exit(PyObject *self, PyObject *unused)
static PyObject * static PyObject *
oss_fileno(oss_audio_t *self, PyObject *unused) oss_fileno(oss_audio_t *self, PyObject *unused)
{ {
if (!_is_fd_valid(self->fd))
return NULL;
return PyLong_FromLong(self->fd); return PyLong_FromLong(self->fd);
} }
@ -503,6 +555,9 @@ oss_setparameters(oss_audio_t *self, PyObject *args)
int fmt, channels, rate; int fmt, channels, rate;
PyObject * rv; /* return tuple (fmt, channels, rate) */ PyObject * rv; /* return tuple (fmt, channels, rate) */
if (!_is_fd_valid(self->fd))
return NULL;
if (!PyArg_ParseTuple(args, "iii|i:setparameters", if (!PyArg_ParseTuple(args, "iii|i:setparameters",
&wanted_fmt, &wanted_channels, &wanted_rate, &wanted_fmt, &wanted_channels, &wanted_rate,
&strict)) &strict))
@ -593,6 +648,9 @@ oss_bufsize(oss_audio_t *self, PyObject *unused)
audio_buf_info ai; audio_buf_info ai;
int nchannels=0, ssize=0; int nchannels=0, ssize=0;
if (!_is_fd_valid(self->fd))
return NULL;
if (_ssize(self, &nchannels, &ssize) < 0 || !nchannels || !ssize) { if (_ssize(self, &nchannels, &ssize) < 0 || !nchannels || !ssize) {
PyErr_SetFromErrno(PyExc_IOError); PyErr_SetFromErrno(PyExc_IOError);
return NULL; return NULL;
@ -612,6 +670,9 @@ oss_obufcount(oss_audio_t *self, PyObject *unused)
audio_buf_info ai; audio_buf_info ai;
int nchannels=0, ssize=0; int nchannels=0, ssize=0;
if (!_is_fd_valid(self->fd))
return NULL;
if (_ssize(self, &nchannels, &ssize) < 0 || !nchannels || !ssize) { if (_ssize(self, &nchannels, &ssize) < 0 || !nchannels || !ssize) {
PyErr_SetFromErrno(PyExc_IOError); PyErr_SetFromErrno(PyExc_IOError);
return NULL; return NULL;
@ -632,6 +693,9 @@ oss_obuffree(oss_audio_t *self, PyObject *unused)
audio_buf_info ai; audio_buf_info ai;
int nchannels=0, ssize=0; int nchannels=0, ssize=0;
if (!_is_fd_valid(self->fd))
return NULL;
if (_ssize(self, &nchannels, &ssize) < 0 || !nchannels || !ssize) { if (_ssize(self, &nchannels, &ssize) < 0 || !nchannels || !ssize) {
PyErr_SetFromErrno(PyExc_IOError); PyErr_SetFromErrno(PyExc_IOError);
return NULL; return NULL;
@ -649,6 +713,9 @@ oss_getptr(oss_audio_t *self, PyObject *unused)
count_info info; count_info info;
int req; int req;
if (!_is_fd_valid(self->fd))
return NULL;
if (self->mode == O_RDONLY) if (self->mode == O_RDONLY)
req = SNDCTL_DSP_GETIPTR; req = SNDCTL_DSP_GETIPTR;
else else
@ -679,6 +746,9 @@ oss_mixer_close(oss_mixer_t *self, PyObject *unused)
static PyObject * static PyObject *
oss_mixer_fileno(oss_mixer_t *self, PyObject *unused) oss_mixer_fileno(oss_mixer_t *self, PyObject *unused)
{ {
if (!_is_fd_valid(self->fd))
return NULL;
return PyLong_FromLong(self->fd); return PyLong_FromLong(self->fd);
} }
@ -687,6 +757,9 @@ oss_mixer_fileno(oss_mixer_t *self, PyObject *unused)
static PyObject * static PyObject *
oss_mixer_controls(oss_mixer_t *self, PyObject *args) oss_mixer_controls(oss_mixer_t *self, PyObject *args)
{ {
if (!_is_fd_valid(self->fd))
return NULL;
return _do_ioctl_1_internal(self->fd, args, "controls", return _do_ioctl_1_internal(self->fd, args, "controls",
SOUND_MIXER_READ_DEVMASK); SOUND_MIXER_READ_DEVMASK);
} }
@ -694,6 +767,9 @@ oss_mixer_controls(oss_mixer_t *self, PyObject *args)
static PyObject * static PyObject *
oss_mixer_stereocontrols(oss_mixer_t *self, PyObject *args) oss_mixer_stereocontrols(oss_mixer_t *self, PyObject *args)
{ {
if (!_is_fd_valid(self->fd))
return NULL;
return _do_ioctl_1_internal(self->fd, args, "stereocontrols", return _do_ioctl_1_internal(self->fd, args, "stereocontrols",
SOUND_MIXER_READ_STEREODEVS); SOUND_MIXER_READ_STEREODEVS);
} }
@ -701,6 +777,9 @@ oss_mixer_stereocontrols(oss_mixer_t *self, PyObject *args)
static PyObject * static PyObject *
oss_mixer_reccontrols(oss_mixer_t *self, PyObject *args) oss_mixer_reccontrols(oss_mixer_t *self, PyObject *args)
{ {
if (!_is_fd_valid(self->fd))
return NULL;
return _do_ioctl_1_internal(self->fd, args, "reccontrols", return _do_ioctl_1_internal(self->fd, args, "reccontrols",
SOUND_MIXER_READ_RECMASK); SOUND_MIXER_READ_RECMASK);
} }
@ -710,6 +789,9 @@ oss_mixer_get(oss_mixer_t *self, PyObject *args)
{ {
int channel, volume; int channel, volume;
if (!_is_fd_valid(self->fd))
return NULL;
/* Can't use _do_ioctl_1 because of encoded arg thingy. */ /* Can't use _do_ioctl_1 because of encoded arg thingy. */
if (!PyArg_ParseTuple(args, "i:get", &channel)) if (!PyArg_ParseTuple(args, "i:get", &channel))
return NULL; return NULL;
@ -730,6 +812,9 @@ oss_mixer_set(oss_mixer_t *self, PyObject *args)
{ {
int channel, volume, leftVol, rightVol; int channel, volume, leftVol, rightVol;
if (!_is_fd_valid(self->fd))
return NULL;
/* Can't use _do_ioctl_1 because of encoded arg thingy. */ /* Can't use _do_ioctl_1 because of encoded arg thingy. */
if (!PyArg_ParseTuple(args, "i(ii):set", &channel, &leftVol, &rightVol)) if (!PyArg_ParseTuple(args, "i(ii):set", &channel, &leftVol, &rightVol))
return NULL; return NULL;
@ -755,6 +840,9 @@ oss_mixer_set(oss_mixer_t *self, PyObject *args)
static PyObject * static PyObject *
oss_mixer_get_recsrc(oss_mixer_t *self, PyObject *args) oss_mixer_get_recsrc(oss_mixer_t *self, PyObject *args)
{ {
if (!_is_fd_valid(self->fd))
return NULL;
return _do_ioctl_1_internal(self->fd, args, "get_recsrc", return _do_ioctl_1_internal(self->fd, args, "get_recsrc",
SOUND_MIXER_READ_RECSRC); SOUND_MIXER_READ_RECSRC);
} }
@ -762,6 +850,9 @@ oss_mixer_get_recsrc(oss_mixer_t *self, PyObject *args)
static PyObject * static PyObject *
oss_mixer_set_recsrc(oss_mixer_t *self, PyObject *args) oss_mixer_set_recsrc(oss_mixer_t *self, PyObject *args)
{ {
if (!_is_fd_valid(self->fd))
return NULL;
return _do_ioctl_1(self->fd, args, "set_recsrc", return _do_ioctl_1(self->fd, args, "set_recsrc",
SOUND_MIXER_WRITE_RECSRC); SOUND_MIXER_WRITE_RECSRC);
} }