diff options
author | Tim Peters <tim.peters@gmail.com> | 2001-12-07 00:37:39 (GMT) |
---|---|---|
committer | Tim Peters <tim.peters@gmail.com> | 2001-12-07 00:37:39 (GMT) |
commit | eb4b7bad336481a34b2db01cbea809de726f9698 (patch) | |
tree | e17e71131b2ba387357dee0a40a55330cecf056c /Modules | |
parent | b404145936cb4363b5ee83b5ef0de96c1353d26e (diff) | |
download | cpython-eb4b7bad336481a34b2db01cbea809de726f9698.zip cpython-eb4b7bad336481a34b2db01cbea809de726f9698.tar.gz cpython-eb4b7bad336481a34b2db01cbea809de726f9698.tar.bz2 |
audioop_ratecv() again: settle for a sloppier upper bound that's less
obnoxious to compute and easier to explain. No compromise on safety.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/audioop.c | 53 |
1 files changed, 19 insertions, 34 deletions
diff --git a/Modules/audioop.c b/Modules/audioop.c index d23ee2a..d9a398f 100644 --- a/Modules/audioop.c +++ b/Modules/audioop.c @@ -2,7 +2,6 @@ /* audioopmodule - Module to detect peak values in arrays */ #include "Python.h" -#include <math.h> #if SIZEOF_INT == 4 typedef int Py_Int32; @@ -981,46 +980,32 @@ audioop_ratecv(PyObject *self, PyObject *args) /* There are len input frames, so we need (mathematically) ceiling(len*outrate/inrate) output frames, and each frame requires bytes_per_frame bytes. Computing this - without spurious overflow is the challenge. */ - int ceiling; /* the number of output frames, eventually */ + without spurious overflow is the challenge; we can + settle for a reasonable upper bound, though. */ + int ceiling; /* the number of output frames */ int nbytes; /* the number of output bytes needed */ int q = len / inrate; - int r = len - q * inrate; - /* Now len = q * inrate + r exactly, so - len*outrate/inrate = - (q*inrate+r)*outrate/inrate = - (q*inrate*outrate + r*outrate)/inrate = - q*outrate + r*outrate/inrate exactly. - q*outrate is an exact integer, so the ceiling we're after is - q*outrate + ceiling(r*outrate/inrate). */ - ceiling = q * outrate; - if (ceiling / outrate != q) { - PyErr_SetString(PyExc_MemoryError, - "not enough memory for output buffer"); - goto exit; - } - /* Since r = len % inrate, in particular r < inrate. So - r * outrate / inrate = (r / inrate) * outrate < outrate, - so ceiling(r * outrate / inrate) <= outrate: the final - result fits in an int -- it can't overflow. */ - assert(r < inrate); - q = (int)ceil((double)r * (double)outrate / (double)inrate); - assert(q <= outrate); - ceiling += q; - if (ceiling < 0) { - PyErr_SetString(PyExc_MemoryError, - "not enough memory for output buffer"); - goto exit; - } + /* Now len = q * inrate + r exactly (with r = len % inrate), + and this is less than q * inrate + inrate = (q+1)*inrate. + So a reasonable upper bound on len*outrate/inrate is + ((q+1)*inrate)*outrate/inrate = + (q+1)*outrate. + */ + ceiling = (q+1) * outrate; nbytes = ceiling * bytes_per_frame; - if (nbytes / bytes_per_frame != ceiling) { + /* See whether anything overflowed; if not, get the space. */ + if (q+1 < 0 || + ceiling / outrate != q+1 || + nbytes / bytes_per_frame != ceiling) + str = NULL; + else + str = PyString_FromStringAndSize(NULL, nbytes); + + if (str == NULL) { PyErr_SetString(PyExc_MemoryError, "not enough memory for output buffer"); goto exit; } - str = PyString_FromStringAndSize(NULL, nbytes); - if (str == NULL) - goto exit; } ncp = PyString_AsString(str); |