aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker RĂ¼melin <vr_qemu@t-online.de>2022-09-23 20:36:40 +0200
committerGerd Hoffmann <kraxel@redhat.com>2022-10-11 10:17:08 +0200
commitb6d93282ccac79e42d87d02652db353894cd1db9 (patch)
treed65cf97b4108cdbf99c6f2eefc4e637970672668
parentb73ef11ff68f05418c8b60945b1e1783a72bd822 (diff)
downloadqemu-b6d93282ccac79e42d87d02652db353894cd1db9.zip
qemu-b6d93282ccac79e42d87d02652db353894cd1db9.tar.gz
qemu-b6d93282ccac79e42d87d02652db353894cd1db9.tar.bz2
audio: prevent an integer overflow in resampling code
There are corner cases where rate->opos can overflow. For example, if QEMU is started with -audiodev pa,id=audio0, out.frequency=11025 -device ich9-intel-hda -device hda-duplex, audiodev=audio0 and the guest plays audio with a sampling frequency of 44100Hz, rate->opos will overflow after 27.05h and the audio stream will be silent for a long time. To prevent a rate->opos and also a rate->ipos overflow, both are wrapped around after a short time. The wrap around point rate->ipos >= 0x10001 is an arbitrarily selected value and can be any small value, 0 and 1 included. The comment that an ipos overflow will result in an infinite loop has been removed, because in this case the resampling code only generates no more output samples and the audio stream stalls. However, there is no infinite loop. Signed-off-by: Volker RĂ¼melin <vr_qemu@t-online.de> Message-Id: <20220923183640.8314-12-vr_qemu@t-online.de> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
-rw-r--r--audio/rate_template.h11
1 files changed, 6 insertions, 5 deletions
diff --git a/audio/rate_template.h b/audio/rate_template.h
index f94c940..b432719 100644
--- a/audio/rate_template.h
+++ b/audio/rate_template.h
@@ -72,11 +72,6 @@ void NAME (void *opaque, struct st_sample *ibuf, struct st_sample *obuf,
ilast = *ibuf++;
rate->ipos++;
- /* if ipos overflow, there is a infinite loop */
- if (rate->ipos == 0xffffffff) {
- rate->ipos = 1;
- rate->opos = rate->opos & 0xffffffff;
- }
/* See if we finished the input buffer yet */
if (ibuf >= iend) {
goto the_end;
@@ -85,6 +80,12 @@ void NAME (void *opaque, struct st_sample *ibuf, struct st_sample *obuf,
icur = *ibuf;
+ /* wrap ipos and opos around long before they overflow */
+ if (rate->ipos >= 0x10001) {
+ rate->ipos = 1;
+ rate->opos &= 0xffffffff;
+ }
+
/* interpolate */
#ifdef FLOAT_MIXENG
#ifdef RECIPROCAL